From 5b913e8fc76c3811f0bb73f83c096ef3b2281962 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 29 Jul 2020 06:49:55 +0000 Subject: [PATCH 001/165] Update pytest requirement from <6 to <7 Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/1.0.0b3...6.0.0) Signed-off-by: dependabot-preview[bot] --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) mode change 100755 => 100644 setup.py diff --git a/requirements.txt b/requirements.txt index 672abb0..cf1e778 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ schema-salad >= 5.0.20200220195218, <8 junit-xml >= 1.8 -pytest < 6 +pytest < 7 diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 index 58663c6..128e127 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ install_requires=install_requires, test_suite="tests", setup_requires=[] + pytest_runner, - tests_require=["pytest<5"], + tests_require=["pytest<7"], entry_points={ "console_scripts": [ "cwltest=cwltest:main", From 3b05d04a8027ae2977179ae053995aa1c5d9d569 Mon Sep 17 00:00:00 2001 From: Rupert Nash Date: Thu, 22 Apr 2021 17:20:42 +0100 Subject: [PATCH 002/165] allow exclusion of tests by name or number --- cwltest/__init__.py | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/cwltest/__init__.py b/cwltest/__init__.py index d192298..7f9f4e3 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -270,6 +270,18 @@ def arg_parser(): # type: () -> argparse.ArgumentParser default=None, help="Run specific tests using their short names separated by comma", ) + parser.add_argument( + "-N", + type=str, + default=None, + help="Exclude specific tests by number, format is 1,3-6,9", + ) + parser.add_argument( + "-S", + type=str, + default=None, + help="Exclude specific tests by short names separated by comma", + ) parser.add_argument( "--tool", type=str, @@ -340,6 +352,15 @@ def arg_parser(): # type: () -> argparse.ArgumentParser return parser +def expand_number_range(nr: str) -> List[int]: + ans: List[int] = [] + for s in nr.split(","): + sp = s.split("-") + if len(sp) == 2: + ans.extend(range(int(sp[0]) - 1, int(sp[1]))) + else: + ans.append(int(s) - 1) + return ans def main(): # type: () -> int @@ -430,12 +451,7 @@ def main(): # type: () -> int if args.n is not None or args.s is not None: ntest = [] if args.n is not None: - for s in args.n.split(","): - sp = s.split("-") - if len(sp) == 2: - ntest.extend(list(range(int(sp[0]) - 1, int(sp[1])))) - else: - ntest.append(int(s) - 1) + ntest = expand_number_range(args.n) if args.s is not None: for s in args.s.split(","): test_number = get_test_number_by_key(tests, "short_name", s) @@ -447,6 +463,20 @@ def main(): # type: () -> int else: ntest = list(range(0, len(tests))) + exclude_n = [] + if args.N is not None: + exclude_n = expand_number_range(args.N) + if args.S is not None: + for s in args.S.split(","): + test_number = get_test_number_by_key(tests, "short_name", s) + if test_number: + exclude_n.append(test_number) + else: + _logger.error('Test with short name "%s" not found ', s) + return 1 + + ntest = list(filter(lambda x: x not in exclude_n, ntest)) + total = 0 with ThreadPoolExecutor(max_workers=args.j) as executor: jobs = [ From ffed6d87e4ad024d464dc279759e11be8c8d794b Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 23 Apr 2021 14:14:09 +0200 Subject: [PATCH 003/165] update release script for Python3.9 compat --- Makefile | 6 ++--- release-test.sh | 60 ++++++++++++++++++++++++------------------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index b5bcd1c..637cb4c 100644 --- a/Makefile +++ b/Makefile @@ -60,12 +60,12 @@ install: FORCE dist: dist/${MODULE}-$(VERSION).tar.gz dist/${MODULE}-$(VERSION).tar.gz: $(SOURCES) - ./setup.py sdist bdist_wheel + python setup.py sdist bdist_wheel ## clean : clean up all temporary / machine-generated files clean: FORCE rm -f ${MODILE}/*.pyc tests/*.pyc - ./setup.py clean --all || true + python setup.py clean --all || true rm -Rf .coverage rm -f diff-cover.html @@ -125,7 +125,7 @@ diff-cover.html: coverage-gcovr.xml coverage.xml ## test : run the ${MODULE} test suite test: all - ./setup.py test + python setup.py test sloccount.sc: ${PYSOURCES} Makefile sloccount --duplicates --wide --details $^ > $@ diff --git a/release-test.sh b/release-test.sh index a44e7c3..3fb3a1f 100755 --- a/release-test.sh +++ b/release-test.sh @@ -3,14 +3,15 @@ set -e set -x +export LC_ALL=C + package=cwltest module=cwltest slug=${TRAVIS_PULL_REQUEST_SLUG:=common-workflow-language/${module}} repo=https://github.com/${slug}.git run_tests="bin/py.test --pyargs ${module}" -pipver=18 # minimum required version of pip -setupver=40.3 # minimum required version of setuptools -PYVER=${PYVER:=3} +pipver=20.3b1 # minimum required version of pip for Python 3.9 +setuptoolsver=41.1.0 # required for Python 3.9 rm -Rf "testenv${PYVER}_"? || /bin/true @@ -18,64 +19,63 @@ export HEAD=${TRAVIS_PULL_REQUEST_SHA:-$(git rev-parse HEAD)} if [ "${RELEASE_SKIP}" != "head" ] then - virtualenv "testenv${PYVER}_1" -p "python${PYVER}" + python3 -m venv testenv1 # First we test the head # shellcheck source=/dev/null - source "testenv${PYVER}_1/bin/activate" - rm -f "testenv${PYVER}_1/lib/python-wheels/setuptools"* - pip install --force-reinstall -U pip==${pipver} - pip install setuptools==${setupver} wheel + source testenv1/bin/activate + rm -Rf testenv1/local + rm -f testenv1/lib/python-wheels/setuptools* \ + && pip install --force-reinstall -U pip==${pipver} \ + && pip install setuptools==${setuptoolsver} wheel make install-dependencies make test pip uninstall -y ${package} || true; pip uninstall -y ${package} \ || true; make install - mkdir "testenv${PYVER}_1/not-${module}" + mkdir testenv1/not-${module} # if there is a subdir named '${module}' py.test will execute tests # there instead of the installed module's tests - - pushd "testenv${PYVER}_1/not-${module}" + pushd testenv1/not-${module} # shellcheck disable=SC2086 ../${run_tests}; popd fi - -virtualenv "testenv${PYVER}_2" -p "python${PYVER}" -virtualenv "testenv${PYVER}_3" -p "python${PYVER}" -virtualenv "testenv${PYVER}_4" -p "python${PYVER}" -virtualenv "testenv${PYVER}_5" -p "python${PYVER}" - +python3 -m venv testenv2 +python3 -m venv testenv3 +python3 -m venv testenv4 +python3 -m venv testenv5 +rm -Rf testenv[2345]/local # Secondly we test via pip -pushd "testenv${PYVER}_2" +pushd testenv2 # shellcheck source=/dev/null source bin/activate -rm lib/python-wheels/setuptools* \ +rm -f lib/python-wheels/setuptools* \ && pip install --force-reinstall -U pip==${pipver} \ - && pip install setuptools==${setupver} wheel + && pip install setuptools==${setuptoolsver} wheel # The following can fail if you haven't pushed your commits to ${repo} pip install -e "git+${repo}@${HEAD}#egg=${package}" pushd src/${package} make install-dependencies make dist make test -cp dist/${package}*tar.gz "../../../testenv${PYVER}_3/" -cp dist/${module}*whl "../../../testenv${PYVER}_4/" +cp dist/${package}*tar.gz ../../../testenv3/ +cp dist/${module}*whl ../../../testenv4/ pip uninstall -y ${package} || true; pip uninstall -y ${package} || true; make install popd # ../.. no subdir named ${proj} here, safe for py.testing the installed module # shellcheck disable=SC2086 ${run_tests} popd -# Is the source distribution in testenv${PYVER}_2 complete enough to build +# Is the source distribution in testenv2 complete enough to build # another functional distribution? -pushd "testenv${PYVER}_3/" +pushd testenv3/ # shellcheck source=/dev/null source bin/activate -rm lib/python-wheels/setuptools* \ +rm -f lib/python-wheels/setuptools* \ && pip install --force-reinstall -U pip==${pipver} \ - && pip install setuptools==${setupver} wheel + && pip install setuptools==${setuptoolsver} wheel pip install ${package}*tar.gz pip install pytest\<5 mkdir out @@ -91,14 +91,14 @@ pushd ../not-${module} popd popd -# Is the wheel in testenv${PYVER}_2 installable and will it pass the tests +# Is the wheel in testenv2 installable and will it pass the tests -pushd "testenv${PYVER}_4/" +pushd testenv4/ # shellcheck source=/dev/null source bin/activate -rm lib/python-wheels/setuptools* \ +rm -f lib/python-wheels/setuptools* \ && pip install --force-reinstall -U pip==${pipver} \ - && pip install setuptools==${setupver} wheel + && pip install setuptools==${setuptoolsver} wheel pip install ${module}*.whl pip install pytest\<5 mkdir not-${module} From 60dbec1b846e338dbda0a864326ef32fdb98de35 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 23 Apr 2021 14:46:33 +0200 Subject: [PATCH 004/165] make new release --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 128e127..26a4a1d 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ setup( name="cwltest", - version="2.0", + version="2.1", description="Common workflow language testing framework", long_description=open(README).read(), long_description_content_type="text/x-rst", From 20810aaa6aa4bffcba14c8c6e52ada170fac28dd Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 23 Apr 2021 15:00:11 +0200 Subject: [PATCH 005/165] match Makefile to release-test.sh --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 637cb4c..ca72a3f 100644 --- a/Makefile +++ b/Makefile @@ -156,11 +156,11 @@ release-test: FORCE release: FORCE PYVER=3 ./release-test.sh - . testenv3_2/bin/activate && \ - testenv3_2/src/${MODULE}/setup.py sdist bdist_wheel - . testenv3_2/bin/activate && \ + . testenv2/bin/activate && \ + testenv2/src/${MODULE}/setup.py sdist bdist_wheel + . testenv2/bin/activate && \ pip install twine && \ - twine upload testenv3_2/src/${MODULE}/dist/*whl && \ + twine upload testenv2/src/${MODULE}/dist/*whl && \ git tag ${VERSION} && git push --tags FORCE: From a217026c37c9abe2f8fac9acdc529b09931d317f Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 23 Apr 2021 15:01:20 +0200 Subject: [PATCH 006/165] bump version in Makefile as well --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ca72a3f..2d9ea30 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ DEVPKGS=pycodestyle diff_cover pylint coverage pydocstyle flake8 \ pytest pytest-xdist isort DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage pydocstyle sloccount \ python-flake8 python-mock shellcheck -VERSION=2.0.$(shell TZ=UTC git log --first-parent --max-count=1 \ +VERSION=2.1.$(shell TZ=UTC git log --first-parent --max-count=1 \ --format=format:%cd --date=format-local:%Y%m%d%H%M%S) mkfile_dir := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) From 4f1fa3451e74a4add66f82f986703431cb243ed9 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 23 Apr 2021 15:04:52 +0200 Subject: [PATCH 007/165] Don't rely on setup.py being marked executable --- Makefile | 2 +- setup.py | 0 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 setup.py diff --git a/Makefile b/Makefile index 2d9ea30..39aecd8 100644 --- a/Makefile +++ b/Makefile @@ -157,7 +157,7 @@ release-test: FORCE release: FORCE PYVER=3 ./release-test.sh . testenv2/bin/activate && \ - testenv2/src/${MODULE}/setup.py sdist bdist_wheel + python testenv2/src/${MODULE}/setup.py sdist bdist_wheel . testenv2/bin/activate && \ pip install twine && \ twine upload testenv2/src/${MODULE}/dist/*whl && \ diff --git a/setup.py b/setup.py old mode 100644 new mode 100755 From 83f83afc449e932fdcfbc9fd6ed954e3a4f1e1a8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 29 Apr 2021 20:39:15 +0000 Subject: [PATCH 008/165] Upgrade to GitHub-native Dependabot --- .github/dependabot.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..491deae --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: +- package-ecosystem: pip + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 From eabc56ec17ca37a68ad8dc237e9cb953b78218aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Jun 2021 00:37:14 +0000 Subject: [PATCH 009/165] Update schema-salad requirement Updates the requirements on [schema-salad](https://github.com/common-workflow-language/schema_salad) to permit the latest version. - [Release notes](https://github.com/common-workflow-language/schema_salad/releases) - [Commits](https://github.com/common-workflow-language/schema_salad/compare/5.0.20200220195218...8.0.20210624154013) --- updated-dependencies: - dependency-name: schema-salad dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) mode change 100755 => 100644 setup.py diff --git a/requirements.txt b/requirements.txt index cf1e778..de7919c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -schema-salad >= 5.0.20200220195218, <8 +schema-salad >= 5.0.20200220195218, < 9 junit-xml >= 1.8 pytest < 7 diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 index 26a4a1d..a98125b --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ except ImportError: tagger = egg_info_cmd.egg_info -install_requires = ["schema-salad >= 5.0.20200220195218, < 8", "junit-xml >= 1.8"] +install_requires = ["schema-salad >= 5.0.20200220195218, < 9", "junit-xml >= 1.8"] needs_pytest = {"pytest", "test", "ptr"}.intersection(sys.argv) pytest_runner = ["pytest < 6", "pytest-runner < 5"] if needs_pytest else [] From eabe89614a1f7fb588ad49bda97a991740f43b1e Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Wed, 1 Sep 2021 15:35:43 +0200 Subject: [PATCH 010/165] modernize --- .github/workflows/ci-tests.yml | 129 ++++++++++++++++++ .travis.yml | 64 --------- MANIFEST.in | 3 +- Makefile | 94 +++++++------ cwltest/__init__.py | 44 +++--- .../future/__init__.pyi => cwltest/py.typed | 0 cwltest/tests/test_categories.py | 2 +- cwltest/tests/test_short_names.py | 2 +- cwltest/tests/util.py | 4 +- mypy.ini | 19 ++- mypy_requirements.txt | 3 + release-test.sh | 30 ++-- requirements.txt | 1 + setup.cfg | 14 +- setup.py | 30 +++- test-requirements.txt | 3 + tox.ini | 88 ++++++------ travis/os_install.sh | 17 --- typeshed/{2and3 => }/avro/__init__.pyi | 0 typeshed/{2and3 => }/avro/schema.pyi | 0 .../{2and3 => }/cachecontrol/__init__.pyi | 0 typeshed/{2and3 => }/cachecontrol/adapter.pyi | 0 typeshed/{2and3 => }/cachecontrol/cache.pyi | 0 .../cachecontrol/caches/__init__.pyi | 0 .../cachecontrol/caches/file_cache.pyi | 0 typeshed/{2and3 => }/cachecontrol/compat.pyi | 0 .../{2and3 => }/cachecontrol/controller.pyi | 0 .../{2and3 => }/cachecontrol/filewrapper.pyi | 0 .../{2and3 => }/cachecontrol/serialize.pyi | 0 typeshed/{2and3 => }/cachecontrol/wrapper.pyi | 0 .../__init__.py => future/__init__.pyi} | 0 .../{2and3 => }/future/utils/__init__.pyi | 0 typeshed/{2and3 => }/galaxy/__init__.pyi | 0 .../galaxy/exceptions/__init__.pyi | 0 .../galaxy/exceptions/error_codes.pyi | 0 typeshed/{2and3 => }/galaxy/jobs/__init__.pyi | 0 .../galaxy/jobs/metrics/__init__.pyi | 0 .../galaxy/jobs/metrics/collectl/__init__.pyi | 0 .../galaxy/jobs/metrics/collectl/cli.pyi | 0 .../jobs/metrics/collectl/processes.pyi | 0 .../galaxy/jobs/metrics/collectl/stats.pyi | 0 .../jobs/metrics/collectl/subsystems.pyi | 0 .../galaxy/jobs/metrics/formatting.pyi | 0 .../jobs/metrics/instrumenters/__init__.pyi | 0 .../jobs/metrics/instrumenters/collectl.pyi | 0 .../jobs/metrics/instrumenters/core.pyi | 0 .../jobs/metrics/instrumenters/cpuinfo.pyi | 0 .../galaxy/jobs/metrics/instrumenters/env.pyi | 0 .../jobs/metrics/instrumenters/meminfo.pyi | 0 .../jobs/metrics/instrumenters/uname.pyi | 0 .../galaxy/objectstore/__init__.pyi | 0 .../galaxy/objectstore/azure_blob.pyi | 0 .../{2and3 => }/galaxy/objectstore/pulsar.pyi | 0 .../{2and3 => }/galaxy/objectstore/rods.pyi | 0 .../{2and3 => }/galaxy/objectstore/s3.pyi | 0 .../objectstore/s3_multipart_upload.pyi | 0 .../{2and3 => }/galaxy/tools/__init__.pyi | 0 .../{2and3 => }/galaxy/tools/cwl/__init__.pyi | 0 .../galaxy/tools/cwl/cwltool_deps.pyi | 0 .../{2and3 => }/galaxy/tools/cwl/parser.pyi | 0 .../galaxy/tools/cwl/representation.pyi | 0 .../galaxy/tools/cwl/runtime_actions.pyi | 0 .../{2and3 => }/galaxy/tools/cwl/schema.pyi | 0 .../galaxy/tools/deps/__init__.pyi | 0 .../galaxy/tools/deps/brew_exts.pyi | 0 .../galaxy/tools/deps/brew_util.pyi | 0 .../galaxy/tools/deps/commands.pyi | 0 .../galaxy/tools/deps/conda_compat.pyi | 0 .../galaxy/tools/deps/conda_util.pyi | 0 .../deps/container_resolvers/__init__.pyi | 0 .../deps/container_resolvers/explicit.pyi | 0 .../tools/deps/container_resolvers/mulled.pyi | 0 .../galaxy/tools/deps/containers.pyi | 0 .../galaxy/tools/deps/dependencies.pyi | 0 .../galaxy/tools/deps/docker_util.pyi | 0 .../galaxy/tools/deps/dockerfiles.pyi | 0 .../galaxy/tools/deps/installable.pyi | 0 .../galaxy/tools/deps/mulled/__init__.pyi | 0 .../galaxy/tools/deps/mulled/_cli.pyi | 0 .../galaxy/tools/deps/mulled/mulled_build.pyi | 0 .../deps/mulled/mulled_build_channel.pyi | 0 .../tools/deps/mulled/mulled_build_files.pyi | 0 .../tools/deps/mulled/mulled_build_tool.pyi | 0 .../tools/deps/mulled/mulled_search.pyi | 0 .../galaxy/tools/deps/mulled/util.pyi | 0 .../galaxy/tools/deps/requirements.pyi | 0 .../galaxy/tools/deps/resolvers/__init__.pyi | 0 .../resolvers/brewed_tool_shed_packages.pyi | 0 .../galaxy/tools/deps/resolvers/conda.pyi | 0 .../tools/deps/resolvers/galaxy_packages.pyi | 0 .../galaxy/tools/deps/resolvers/homebrew.pyi | 0 .../galaxy/tools/deps/resolvers/modules.pyi | 0 .../tools/deps/resolvers/resolver_mixins.pyi | 0 .../deps/resolvers/tool_shed_packages.pyi | 0 .../resolvers/unlinked_tool_shed_packages.pyi | 0 .../galaxy/tools/deps/singularity_util.pyi | 0 .../{2and3 => }/galaxy/tools/deps/views.pyi | 0 typeshed/{2and3 => }/galaxy/tools/fetcher.pyi | 0 typeshed/{2and3 => }/galaxy/tools/lint.pyi | 0 .../{2and3 => }/galaxy/tools/lint_util.pyi | 0 .../galaxy/tools/linters/__init__.pyi | 0 .../galaxy/tools/linters/citations.pyi | 0 .../galaxy/tools/linters/command.pyi | 0 .../{2and3 => }/galaxy/tools/linters/cwl.pyi | 0 .../galaxy/tools/linters/general.pyi | 0 .../{2and3 => }/galaxy/tools/linters/help.pyi | 0 .../galaxy/tools/linters/inputs.pyi | 0 .../galaxy/tools/linters/outputs.pyi | 0 .../galaxy/tools/linters/stdio.pyi | 0 .../galaxy/tools/linters/tests.pyi | 0 .../galaxy/tools/linters/xml_order.pyi | 0 typeshed/{2and3 => }/galaxy/tools/loader.pyi | 0 .../galaxy/tools/loader_directory.pyi | 0 .../galaxy/tools/locations/__init__.pyi | 0 .../galaxy/tools/locations/dockstore.pyi | 0 .../galaxy/tools/locations/file.pyi | 0 .../galaxy/tools/locations/http.pyi | 0 .../galaxy/tools/parser/__init__.pyi | 0 .../{2and3 => }/galaxy/tools/parser/cwl.pyi | 0 .../galaxy/tools/parser/factory.pyi | 0 .../galaxy/tools/parser/interface.pyi | 0 .../galaxy/tools/parser/output_actions.pyi | 0 .../tools/parser/output_collection_def.pyi | 0 .../galaxy/tools/parser/output_objects.pyi | 0 .../{2and3 => }/galaxy/tools/parser/util.pyi | 0 .../{2and3 => }/galaxy/tools/parser/xml.pyi | 0 .../{2and3 => }/galaxy/tools/parser/yaml.pyi | 0 .../galaxy/tools/verify/__init__.pyi | 0 .../galaxy/tools/verify/asserts/__init__.pyi | 0 .../galaxy/tools/verify/asserts/tabular.pyi | 0 .../galaxy/tools/verify/asserts/text.pyi | 0 .../galaxy/tools/verify/asserts/xml.pyi | 0 .../galaxy/tools/verify/test_data.pyi | 0 typeshed/{2and3 => }/galaxy/util/__init__.pyi | 0 .../{2and3 => }/galaxy/util/aliaspickler.pyi | 0 typeshed/{2and3 => }/galaxy/util/bunch.pyi | 0 typeshed/{2and3 => }/galaxy/util/checkers.pyi | 0 .../galaxy/util/compression_utils.pyi | 0 .../{2and3 => }/galaxy/util/dictifiable.pyi | 0 .../{2and3 => }/galaxy/util/expressions.pyi | 0 typeshed/{2and3 => }/galaxy/util/filelock.pyi | 0 .../{2and3 => }/galaxy/util/hash_util.pyi | 0 .../{2and3 => }/galaxy/util/heartbeat.pyi | 0 .../{2and3 => }/galaxy/util/image_util.pyi | 0 .../{2and3 => }/galaxy/util/inflection.pyi | 0 typeshed/{2and3 => }/galaxy/util/json.pyi | 0 .../{2and3 => }/galaxy/util/lazy_process.pyi | 0 .../galaxy/util/object_wrapper.pyi | 0 typeshed/{2and3 => }/galaxy/util/odict.pyi | 0 typeshed/{2and3 => }/galaxy/util/oset.pyi | 0 .../{2and3 => }/galaxy/util/plugin_config.pyi | 0 .../{2and3 => }/galaxy/util/properties.pyi | 0 .../{2and3 => }/galaxy/util/simplegraph.pyi | 0 typeshed/{2and3 => }/galaxy/util/sleeper.pyi | 0 typeshed/{2and3 => }/galaxy/util/sockets.pyi | 0 typeshed/{2and3 => }/galaxy/util/specs.pyi | 0 typeshed/{2and3 => }/galaxy/util/sqlite.pyi | 0 .../{2and3 => }/galaxy/util/submodules.pyi | 0 typeshed/{2and3 => }/galaxy/util/topsort.pyi | 0 .../{2and3 => }/galaxy/util/xml_macros.pyi | 0 typeshed/{2and3 => }/junit_xml.pyi | 0 typeshed/{2and3 => }/mistune.pyi | 0 typeshed/{2and3 => }/rdflib/__init__.pyi | 0 typeshed/{2and3 => }/rdflib/events.pyi | 0 typeshed/{2and3 => }/rdflib/exceptions.pyi | 0 typeshed/{2and3 => }/rdflib/graph.pyi | 0 typeshed/{2and3 => }/rdflib/namespace.pyi | 0 typeshed/{2and3 => }/rdflib/parser.pyi | 0 typeshed/{2and3 => }/rdflib/plugin.pyi | 0 .../{2and3 => }/rdflib/plugins/__init__.pyi | 0 .../rdflib/plugins/parsers/__init__.pyi | 0 .../rdflib/plugins/parsers/notation3.pyi | 0 typeshed/{2and3 => }/rdflib/query.pyi | 0 typeshed/{2and3 => }/rdflib/serializer.pyi | 0 typeshed/{2and3 => }/rdflib/store.pyi | 0 typeshed/{2and3 => }/rdflib/term.pyi | 0 typeshed/{2and3 => }/rdflib/util.pyi | 0 typeshed/{3/urllib => ruamel}/__init__.py | 0 typeshed/{2and3 => }/select.pyi | 0 typeshed/{2and3 => }/shellescape/__init__.pyi | 0 typeshed/{2and3 => }/shellescape/main.pyi | 0 typeshed/urllib/__init__.py | 0 typeshed/{3 => }/urllib/parse.pyi | 0 typeshed/{3 => }/urllib/subprocess.pyi | 0 184 files changed, 331 insertions(+), 216 deletions(-) create mode 100644 .github/workflows/ci-tests.yml delete mode 100644 .travis.yml rename typeshed/2and3/future/__init__.pyi => cwltest/py.typed (100%) create mode 100644 mypy_requirements.txt create mode 100644 test-requirements.txt delete mode 100644 travis/os_install.sh rename typeshed/{2and3 => }/avro/__init__.pyi (100%) rename typeshed/{2and3 => }/avro/schema.pyi (100%) rename typeshed/{2and3 => }/cachecontrol/__init__.pyi (100%) rename typeshed/{2and3 => }/cachecontrol/adapter.pyi (100%) rename typeshed/{2and3 => }/cachecontrol/cache.pyi (100%) rename typeshed/{2and3 => }/cachecontrol/caches/__init__.pyi (100%) rename typeshed/{2and3 => }/cachecontrol/caches/file_cache.pyi (100%) rename typeshed/{2and3 => }/cachecontrol/compat.pyi (100%) rename typeshed/{2and3 => }/cachecontrol/controller.pyi (100%) rename typeshed/{2and3 => }/cachecontrol/filewrapper.pyi (100%) rename typeshed/{2and3 => }/cachecontrol/serialize.pyi (100%) rename typeshed/{2and3 => }/cachecontrol/wrapper.pyi (100%) rename typeshed/{2and3/ruamel/__init__.py => future/__init__.pyi} (100%) rename typeshed/{2and3 => }/future/utils/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/exceptions/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/exceptions/error_codes.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/metrics/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/metrics/collectl/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/metrics/collectl/cli.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/metrics/collectl/processes.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/metrics/collectl/stats.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/metrics/collectl/subsystems.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/metrics/formatting.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/metrics/instrumenters/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/metrics/instrumenters/collectl.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/metrics/instrumenters/core.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/metrics/instrumenters/cpuinfo.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/metrics/instrumenters/env.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/metrics/instrumenters/meminfo.pyi (100%) rename typeshed/{2and3 => }/galaxy/jobs/metrics/instrumenters/uname.pyi (100%) rename typeshed/{2and3 => }/galaxy/objectstore/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/objectstore/azure_blob.pyi (100%) rename typeshed/{2and3 => }/galaxy/objectstore/pulsar.pyi (100%) rename typeshed/{2and3 => }/galaxy/objectstore/rods.pyi (100%) rename typeshed/{2and3 => }/galaxy/objectstore/s3.pyi (100%) rename typeshed/{2and3 => }/galaxy/objectstore/s3_multipart_upload.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/cwl/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/cwl/cwltool_deps.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/cwl/parser.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/cwl/representation.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/cwl/runtime_actions.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/cwl/schema.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/brew_exts.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/brew_util.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/commands.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/conda_compat.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/conda_util.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/container_resolvers/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/container_resolvers/explicit.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/container_resolvers/mulled.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/containers.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/dependencies.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/docker_util.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/dockerfiles.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/installable.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/mulled/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/mulled/_cli.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/mulled/mulled_build.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/mulled/mulled_build_channel.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/mulled/mulled_build_files.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/mulled/mulled_build_tool.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/mulled/mulled_search.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/mulled/util.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/requirements.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/resolvers/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/resolvers/brewed_tool_shed_packages.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/resolvers/conda.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/resolvers/galaxy_packages.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/resolvers/homebrew.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/resolvers/modules.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/resolvers/resolver_mixins.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/resolvers/tool_shed_packages.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/resolvers/unlinked_tool_shed_packages.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/singularity_util.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/deps/views.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/fetcher.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/lint.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/lint_util.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/linters/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/linters/citations.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/linters/command.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/linters/cwl.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/linters/general.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/linters/help.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/linters/inputs.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/linters/outputs.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/linters/stdio.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/linters/tests.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/linters/xml_order.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/loader.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/loader_directory.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/locations/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/locations/dockstore.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/locations/file.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/locations/http.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/parser/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/parser/cwl.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/parser/factory.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/parser/interface.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/parser/output_actions.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/parser/output_collection_def.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/parser/output_objects.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/parser/util.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/parser/xml.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/parser/yaml.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/verify/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/verify/asserts/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/verify/asserts/tabular.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/verify/asserts/text.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/verify/asserts/xml.pyi (100%) rename typeshed/{2and3 => }/galaxy/tools/verify/test_data.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/__init__.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/aliaspickler.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/bunch.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/checkers.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/compression_utils.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/dictifiable.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/expressions.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/filelock.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/hash_util.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/heartbeat.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/image_util.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/inflection.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/json.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/lazy_process.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/object_wrapper.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/odict.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/oset.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/plugin_config.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/properties.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/simplegraph.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/sleeper.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/sockets.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/specs.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/sqlite.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/submodules.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/topsort.pyi (100%) rename typeshed/{2and3 => }/galaxy/util/xml_macros.pyi (100%) rename typeshed/{2and3 => }/junit_xml.pyi (100%) rename typeshed/{2and3 => }/mistune.pyi (100%) rename typeshed/{2and3 => }/rdflib/__init__.pyi (100%) rename typeshed/{2and3 => }/rdflib/events.pyi (100%) rename typeshed/{2and3 => }/rdflib/exceptions.pyi (100%) rename typeshed/{2and3 => }/rdflib/graph.pyi (100%) rename typeshed/{2and3 => }/rdflib/namespace.pyi (100%) rename typeshed/{2and3 => }/rdflib/parser.pyi (100%) rename typeshed/{2and3 => }/rdflib/plugin.pyi (100%) rename typeshed/{2and3 => }/rdflib/plugins/__init__.pyi (100%) rename typeshed/{2and3 => }/rdflib/plugins/parsers/__init__.pyi (100%) rename typeshed/{2and3 => }/rdflib/plugins/parsers/notation3.pyi (100%) rename typeshed/{2and3 => }/rdflib/query.pyi (100%) rename typeshed/{2and3 => }/rdflib/serializer.pyi (100%) rename typeshed/{2and3 => }/rdflib/store.pyi (100%) rename typeshed/{2and3 => }/rdflib/term.pyi (100%) rename typeshed/{2and3 => }/rdflib/util.pyi (100%) rename typeshed/{3/urllib => ruamel}/__init__.py (100%) rename typeshed/{2and3 => }/select.pyi (100%) rename typeshed/{2and3 => }/shellescape/__init__.pyi (100%) rename typeshed/{2and3 => }/shellescape/main.pyi (100%) create mode 100644 typeshed/urllib/__init__.py rename typeshed/{3 => }/urllib/parse.pyi (100%) rename typeshed/{3 => }/urllib/subprocess.pyi (100%) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml new file mode 100644 index 0000000..cf34d1d --- /dev/null +++ b/.github/workflows/ci-tests.yml @@ -0,0 +1,129 @@ +name: Continous integration tests + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + + tox: + name: CI tests via Tox + + runs-on: ubuntu-20.04 + + strategy: + matrix: + py-ver-major: [3] + py-ver-minor: [6, 7, 8, 9] + step: [lint, unit, mypy] + + env: + py-semver: ${{ format('{0}.{1}', matrix.py-ver-major, matrix.py-ver-minor) }} + TOXENV: ${{ format('py{0}{1}-{2}', matrix.py-ver-major, matrix.py-ver-minor, matrix.step) }} + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: ${{ env.py-semver }} + + - name: Cache for pip + uses: actions/cache@v2 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ matrix.step }}-${{ hashFiles('requirements.txt', 'tox.ini') }} + + - name: Upgrade setuptools and install tox + run: | + pip install -U pip setuptools wheel + pip install tox tox-gh-actions + + - name: MyPy cache + if: ${{ matrix.step == 'mypy' }} + uses: actions/cache@v2 + with: + path: .mypy_cache/${{ env.py-semver }} + key: mypy-${{ env.py-semver }} + + - name: Test with tox + run: tox + + - name: Upload coverage to Codecov + if: ${{ matrix.step == 'unit' }} + uses: codecov/codecov-action@v1 + with: + fail_ci_if_error: true + + tox-style: + name: CI linters via Tox + + runs-on: ubuntu-20.04 + + strategy: + matrix: + step: [lint-readme, pydocstyle] + + env: + py-semver: 3.9 + TOXENV: ${{ format('py39-{0}', matrix.step) }} + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: ${{ env.py-semver }} + + - name: Cache for pip + uses: actions/cache@v2 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ matrix.step }}-${{ hashFiles('requirements.txt') }} + + - name: Upgrade setuptools and install tox + run: | + pip install -U pip setuptools wheel + pip install tox tox-gh-actions + + - if: ${{ matrix.step == 'pydocstyle' && github.event_name == 'pull_request'}} + name: Create local branch for diff-quality for PRs + run: git branch ${{github.base_ref}} origin/${{github.base_ref}} + + - name: Test with tox + run: tox + + release_test: + name: cwltest release test + + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.9 + + - name: Cache for pip + uses: actions/cache@v2 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-release-${{ hashFiles('requirements.txt', 'test-requirements.txt') }} + + - name: Install packages + run: | + pip install -U pip setuptools wheel + pip install virtualenv + + - name: Release test + env: + RELEASE_SKIP: head + run: ./release-test.sh diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 89a8f69..0000000 --- a/.travis.yml +++ /dev/null @@ -1,64 +0,0 @@ -services: - - docker - -matrix: - include: - - os: linux - language: python - python: 3.5 - script: - - tox - - RELEASE_SKIP=head PYVER=3 ${TRAVIS_BUILD_DIR}/release-test.sh - - os: linux - language: python - python: 3.6 - script: - - tox - - RELEASE_SKIP=head PYVER=3 ${TRAVIS_BUILD_DIR}/release-test.sh - - os: linux - language: python - python: 3.7 - script: - - tox - - RELEASE_SKIP=head PYVER=3 ${TRAVIS_BUILD_DIR}/release-test.sh - - os: linux - language: python - python: 3.8 - script: - - tox - - RELEASE_SKIP=head PYVER=3 ${TRAVIS_BUILD_DIR}/release-test.sh - - os: osx - language: generic - env: TRAVIS_PYTHON_VERSION=3.5 PYENV_VERSION=3.5.4 - - os: osx - language: generic - env: TRAVIS_PYTHON_VERSION=3.6 PYENV_VERSION=3.6.3 - - os: osx - language: generic - env: TRAVIS_PYTHON_VERSION=3.7 PYENV_VERSION=3.7.5 - - os: osx - language: generic - env: TRAVIS_PYTHON_VERSION=3.8 PYENV_VERSION=3.8.0 - -install: - - source $TRAVIS_BUILD_DIR/travis/os_install.sh - - pip install tox-travis - -script: - - tox - -before_cache: - - brew cleanup -cache: - pip: true - directories: - - .mypy_cache - - $HOME/.pyenv_cache - - $HOME/Library/Caches/Homebrew - - $HOME/.pyenv/versions - -branches: - only: - - master -notifications: - email: false diff --git a/MANIFEST.in b/MANIFEST.in index 46873cc..6e775fd 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,7 +1,8 @@ -include Makefile gittaggers.py +include Makefile gittaggers.py test-requirements.txt mypy_requirements.txt requirements.txt include cwltest/cwltest-schema.yml include cwltest/tests/* include cwltest/tests/test-data/* include cwltest/tests/test-data/v1.0/* +recursive-include typeshed *.py? global-exclude *~ global-exclude *.pyc diff --git a/Makefile b/Makefile index 39aecd8..e67f0e1 100644 --- a/Makefile +++ b/Makefile @@ -15,36 +15,36 @@ # # Contact: common-workflow-language@googlegroups.com -# make pycodestyle to check for basic Python code compliance -# make autopep8 to fix most pep8 errors +# make format to fix most python formatting errors # make pylint to check Python code for enhanced compliance including naming # and documentation # make coverage-report to check coverage of the python scripts by the tests MODULE=cwltest +PACKAGE=cwltest # `SHELL=bash` doesn't work for some, so don't use BASH-isms like # `[[` conditional expressions. PYSOURCES=$(wildcard ${MODULE}/**.py tests/*.py) setup.py -DEVPKGS=pycodestyle diff_cover pylint coverage pydocstyle flake8 \ - pytest pytest-xdist isort +DEVPKGS=diff_cover black pylint pep257 pydocstyle flake8 tox tox-pyenv \ + isort wheel autoflake flake8-bugbear pyupgrade bandit \ + -rtest-requirements.txt -rmypy_requirements.txt DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage pydocstyle sloccount \ python-flake8 python-mock shellcheck -VERSION=2.1.$(shell TZ=UTC git log --first-parent --max-count=1 \ +VERSION=2.2.$(shell TZ=UTC git log --first-parent --max-count=1 \ --format=format:%cd --date=format-local:%Y%m%d%H%M%S) -mkfile_dir := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) ## all : default task -all: FORCE - pip install -e . +all: dev ## help : print this help message and exit help: Makefile @sed -n 's/^##//p' $< -install-dependencies: install-dep ## install-dep : install most of the development dependencies via pip -install-dep: +install-dep: install-dependencies + +install-dependencies: FORCE pip install --upgrade $(DEVPKGS) pip install -r requirements.txt @@ -52,10 +52,14 @@ install-dep: install-deb-dep: sudo apt-get install $(DEBDEVPKGS) -## install : install the ${MODULE} module and schema-salad-tool +## install : install the ${MODULE} module and cwltest install: FORCE pip install . +## dev : install the ${MODULE} module in dev mode +dev: install-dep + pip install -e . + ## dist : create a module package for distribution dist: dist/${MODULE}-$(VERSION).tar.gz @@ -71,8 +75,11 @@ clean: FORCE # Linting and code style related targets ## sorting imports using isort: https://github.com/timothycrosley/isort -sort_imports: - isort ${MODULE}/*.py tests/*.py setup.py +sort_imports: $(PYSOURCES) + isort $^ + +remove_unused_imports: $(filter-out schema_salad/metaschema.py,$(PYSOURCES)) + autoflake --in-place --remove-all-unused-imports $^ pep257: pydocstyle ## pydocstyle : check Python code style @@ -83,18 +90,21 @@ pydocstyle_report.txt: $(PYSOURCES) pydocstyle setup.py $^ > $@ 2>&1 || true diff_pydocstyle_report: pydocstyle_report.txt - diff-quality --violations=pycodestyle --fail-under=100 $^ + diff-quality --compare-branch=main --violations=pydocstyle --fail-under=100 $^ ## format : check/fix all code indentation and formatting (runs black) format: - black --exclude cwltool/schemas setup.py cwltest + black setup.py cwltest setup.py + +format-check: + black --diff --check setup.py cwltest ## pylint : run static code analysis on Python code pylint: $(PYSOURCES) pylint --msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}" \ $^ -j0|| true -pylint_report.txt: ${PYSOURCES} +pylint_report.txt: $(PYSOURCES) pylint --msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}" \ $^ -j0> $@ || true @@ -102,36 +112,39 @@ diff_pylint_report: pylint_report.txt diff-quality --violations=pylint pylint_report.txt .coverage: $(PYSOURCES) all - coverage run ./setup.py test + python setup.py test --addopts "--cov --cov-config=.coveragerc --cov-report= -n auto ${PYTEST_EXTRA}" coverage.xml: .coverage - python-coverage xml + coverage xml coverage.html: htmlcov/index.html htmlcov/index.html: .coverage - python-coverage html + coverage html @echo Test coverage of the Python code is now in htmlcov/index.html coverage-report: .coverage - python-coverage report + coverage report -diff-cover: coverage-gcovr.xml coverage.xml - diff-cover coverage-gcovr.xml coverage.xml +diff-cover: coverage.xml + diff-cover $^ -diff-cover.html: coverage-gcovr.xml coverage.xml - diff-cover coverage-gcovr.xml coverage.xml \ - --html-report diff-cover.html +diff-cover.html: coverage.xml + diff-cover $^ --html-report $@ ## test : run the ${MODULE} test suite -test: all - python setup.py test +test: $(PYSOURCES) all + python setup.py test ${PYTEST_EXTRA} + +## testcov : run the ${MODULE} test suite and collect coverage +testcov: $(PYSOURCES) + python setup.py test --addopts "--cov" ${PYTEST_EXTRA} -sloccount.sc: ${PYSOURCES} Makefile +sloccount.sc: $(PYSOURCES) Makefile sloccount --duplicates --wide --details $^ > $@ ## sloccount : count lines of code -sloccount: ${PYSOURCES} Makefile +sloccount: $(PYSOURCES) Makefile sloccount $^ list-author-emails: @@ -139,30 +152,33 @@ list-author-emails: @git log --format='%aN,%aE' | sort -u | grep -v 'root' mypy3: mypy -mypy: ${PYSOURCES} +mypy: $(filter-out setup.py gittagger.py,$(PYSOURCES)) if ! test -f $(shell python3 -c 'import ruamel.yaml; import os.path; print(os.path.dirname(ruamel.yaml.__file__))')/py.typed ; \ then \ - rm -Rf typeshed/2and3/ruamel/yaml ; \ + rm -Rf typeshed/ruamel/yaml ; \ ln -s $(shell python3 -c 'import ruamel.yaml; import os.path; print(os.path.dirname(ruamel.yaml.__file__))') \ - typeshed/2and3/ruamel/ ; \ + typeshed/ruamel/ ; \ fi # if minimally required ruamel.yaml version is 0.15.99 or greater, than the above can be removed - MYPYPATH=$$MYPYPATH:typeshed/3:typeshed/2and3 mypy --disallow-untyped-calls \ - --warn-redundant-casts \ - ${MODULE} + MYPYPATH=$$MYPYPATH:typeshed mypy $^ + +pyupgrade: $(filter-out schema_salad/metaschema.py,$(PYSOURCES)) + pyupgrade --exit-zero-even-if-changed --py36-plus $^ release-test: FORCE git diff-index --quiet HEAD -- || ( echo You have uncommited changes, please commit them and try again; false ) ./release-test.sh -release: FORCE - PYVER=3 ./release-test.sh +release: release-test . testenv2/bin/activate && \ - python testenv2/src/${MODULE}/setup.py sdist bdist_wheel + python testenv2/src/${PACKAGE}/setup.py sdist bdist_wheel . testenv2/bin/activate && \ pip install twine && \ - twine upload testenv2/src/${MODULE}/dist/*whl && \ + twine upload testenv2/src/${PACKAGE}/dist/* && \ git tag ${VERSION} && git push --tags +flake8: $(PYSOURCES) + flake8 $^ + FORCE: # Use this to print the value of a Makefile variable diff --git a/cwltest/__init__.py b/cwltest/__init__.py index 7f9f4e3..33eb121 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -38,10 +38,10 @@ DEFAULT_TIMEOUT = 600 # 10 minutes if sys.version_info < (3, 0): - import subprocess32 as subprocess + import subprocess32 as subprocess # nosec from pipes import quote else: - import subprocess + import subprocess # nosec from shlex import quote templock = threading.Lock() @@ -145,7 +145,7 @@ def run_test( start_time = time.time() stderr = subprocess.PIPE if not args.verbose else None - process = subprocess.Popen(test_command, stdout=subprocess.PIPE, stderr=stderr, universal_newlines=True, cwd=cwd) + process = subprocess.Popen(test_command, stdout=subprocess.PIPE, stderr=stderr, universal_newlines=True, cwd=cwd) # nosec outstr, outerr = process.communicate(timeout=timeout) return_code = process.poll() duration = time.time() - start_time @@ -189,16 +189,16 @@ def run_test( _logger.error(outerr) except KeyboardInterrupt: _logger.error( - u"""Test %i interrupted: %s""", + """Test %i interrupted: %s""", test_number, - u" ".join([quote(tc) for tc in test_command]), + " ".join([quote(tc) for tc in test_command]), ) raise except subprocess.TimeoutExpired: _logger.error( - u"""Test %i timed out: %s""", + """Test %i timed out: %s""", test_number, - u" ".join([quote(tc) for tc in test_command]), + " ".join([quote(tc) for tc in test_command]), ) _logger.error(test.get("doc")) return TestResult(2, outstr, outerr, timeout, args.classname, "Test timed out") @@ -379,17 +379,27 @@ def main(): # type: () -> int return 1 schema_resource = pkg_resources.resource_stream(__name__, "cwltest-schema.yml") - cache = {"https://w3id.org/cwl/cwltest/cwltest-schema.yml": schema_resource.read().decode("utf-8")} # type: Optional[Dict[str, Union[str, Graph, bool]]] - (document_loader, - avsc_names, - schema_metadata, - metaschema_loader) = schema_salad.schema.load_schema("https://w3id.org/cwl/cwltest/cwltest-schema.yml", cache=cache) + cache = { + "https://w3id.org/cwl/cwltest/cwltest-schema.yml": schema_resource.read().decode( + "utf-8" + ) + } # type: Optional[Dict[str, Union[str, Graph, bool]]] + ( + document_loader, + avsc_names, + schema_metadata, + metaschema_loader, + ) = schema_salad.schema.load_schema( + "https://w3id.org/cwl/cwltest/cwltest-schema.yml", cache=cache + ) if not isinstance(avsc_names, schema_salad.avro.schema.Names): print(avsc_names) return 1 - tests, metadata = schema_salad.schema.load_and_validate(document_loader, avsc_names, args.test, True) + tests, metadata = schema_salad.schema.load_and_validate( + document_loader, avsc_names, args.test, True + ) failures = 0 unsupported = 0 @@ -421,7 +431,7 @@ def main(): # type: () -> int tags = args.tags.split(",") for t in alltests: ts = t.get("tags", []) - if any((tag in ts for tag in tags)): + if any(tag in ts for tag in tags): tests.append(t) for t in tests: @@ -441,10 +451,10 @@ def main(): # type: () -> int for i, t in enumerate(tests): if t.get("short_name"): print( - u"[%i] %s: %s" % (i + 1, t["short_name"], t.get("doc", "").strip()) + "[%i] %s: %s" % (i + 1, t["short_name"], t.get("doc", "").strip()) ) else: - print(u"[%i] %s" % (i + 1, t.get("doc", "").strip())) + print("[%i] %s" % (i + 1, t.get("doc", "").strip())) return 0 @@ -495,7 +505,7 @@ def main(): # type: () -> int for i, job in zip(ntest, jobs): test_result = job.result() test_case = test_result.create_test_case(tests[i]) - test_case.url = "cwltest:{}#{}".format(suite_name, i + 1) + test_case.url = f"cwltest:{suite_name}#{i + 1}" total += 1 tags = tests[i].get("tags", []) for t in tags: diff --git a/typeshed/2and3/future/__init__.pyi b/cwltest/py.typed similarity index 100% rename from typeshed/2and3/future/__init__.pyi rename to cwltest/py.typed diff --git a/cwltest/tests/test_categories.py b/cwltest/tests/test_categories.py index 3ec6719..71798e9 100644 --- a/cwltest/tests/test_categories.py +++ b/cwltest/tests/test_categories.py @@ -5,7 +5,7 @@ from os import sep as p from .util import run_with_mock_cwl_runner, get_data -import xml.etree.ElementTree as ET +import defusedxml.ElementTree as ET import schema_salad.ref_resolver class TestCategories(unittest.TestCase): diff --git a/cwltest/tests/test_short_names.py b/cwltest/tests/test_short_names.py index ca0367a..6efda7f 100644 --- a/cwltest/tests/test_short_names.py +++ b/cwltest/tests/test_short_names.py @@ -4,7 +4,7 @@ from os import linesep as n from .util import run_with_mock_cwl_runner, get_data -import xml.etree.ElementTree as ET +import defusedxml.ElementTree as ET class TestShortNames(unittest.TestCase): diff --git a/cwltest/tests/util.py b/cwltest/tests/util.py index 3a2bc77..414db00 100644 --- a/cwltest/tests/util.py +++ b/cwltest/tests/util.py @@ -1,7 +1,7 @@ import os import sys -import subprocess +import subprocess # nosec from pkg_resources import ( Requirement, @@ -25,7 +25,7 @@ def get_data(filename): def run_with_mock_cwl_runner(args): - process = subprocess.Popen( + process = subprocess.Popen( # nosec ["cwltest", "--tool", "mock-cwl-runner"] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, diff --git a/mypy.ini b/mypy.ini index 2d48495..6a442f8 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,8 +1,13 @@ [mypy] -# --strict options as of mypy 0.720 +show_error_context = true +show_column_numbers = true +show_error_codes = true +pretty = true + +# --strict options as of mypy 0.910 warn_unused_configs = True -disallow_subclassing_any = True disallow_any_generics = True +disallow_subclassing_any = True disallow_untyped_calls = True disallow_untyped_defs = True disallow_incomplete_defs = True @@ -12,14 +17,8 @@ no_implicit_optional = True warn_redundant_casts = True warn_unused_ignores = True warn_return_any = True -implicit_reexport = True - -[mypy-schema_salad.tests.*] -ignore_errors = True +implicit_reexport = False +strict_equality = True [mypy-ruamel.*] ignore_errors = True - -[mypy-cwltest.tests.*] -ignore_errors = True - diff --git a/mypy_requirements.txt b/mypy_requirements.txt new file mode 100644 index 0000000..e33b163 --- /dev/null +++ b/mypy_requirements.txt @@ -0,0 +1,3 @@ +mypy==0.910 +types-setuptools +types-requests diff --git a/release-test.sh b/release-test.sh index 3fb3a1f..dcb6d90 100755 --- a/release-test.sh +++ b/release-test.sh @@ -7,15 +7,21 @@ export LC_ALL=C package=cwltest module=cwltest -slug=${TRAVIS_PULL_REQUEST_SLUG:=common-workflow-language/${module}} -repo=https://github.com/${slug}.git +if [ "$GITHUB_ACTIONS" = "true" ]; then + # We are running as a GH Action + repo=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git + HEAD=${GITHUB_REF} +else + repo=https://github.com/common-workflow-language/cwltest.git + HEAD=$(git rev-parse HEAD) +fi run_tests="bin/py.test --pyargs ${module}" pipver=20.3b1 # minimum required version of pip for Python 3.9 setuptoolsver=41.1.0 # required for Python 3.9 +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" -rm -Rf "testenv${PYVER}_"? || /bin/true +rm -Rf testenv? || /bin/true -export HEAD=${TRAVIS_PULL_REQUEST_SHA:-$(git rev-parse HEAD)} if [ "${RELEASE_SKIP}" != "head" ] then @@ -27,10 +33,9 @@ then rm -f testenv1/lib/python-wheels/setuptools* \ && pip install --force-reinstall -U pip==${pipver} \ && pip install setuptools==${setuptoolsver} wheel - make install-dependencies + pip install -rtest-requirements.txt make test - pip uninstall -y ${package} || true; pip uninstall -y ${package} \ - || true; make install + pip uninstall -y ${package} || true; pip uninstall -y ${package} || true; make install mkdir testenv1/not-${module} # if there is a subdir named '${module}' py.test will execute tests # there instead of the installed module's tests @@ -56,7 +61,7 @@ rm -f lib/python-wheels/setuptools* \ # The following can fail if you haven't pushed your commits to ${repo} pip install -e "git+${repo}@${HEAD}#egg=${package}" pushd src/${package} -make install-dependencies +pip install -rtest-requirements.txt make dist make test cp dist/${package}*tar.gz ../../../testenv3/ @@ -76,13 +81,16 @@ source bin/activate rm -f lib/python-wheels/setuptools* \ && pip install --force-reinstall -U pip==${pipver} \ && pip install setuptools==${setuptoolsver} wheel -pip install ${package}*tar.gz -pip install pytest\<5 +package_tar=$(find . -name "${package}*tar.gz") +pip install "-r${DIR}/test-requirements.txt" +pip install "${package_tar}" mkdir out tar --extract --directory=out -z -f ${package}*.tar.gz pushd out/${package}* make dist make test +pip install "-r${DIR}/mypy_requirements.txt" +make mypy pip uninstall -y ${package} || true; pip uninstall -y ${package} || true; make install mkdir ../not-${module} pushd ../not-${module} @@ -100,7 +108,7 @@ rm -f lib/python-wheels/setuptools* \ && pip install --force-reinstall -U pip==${pipver} \ && pip install setuptools==${setuptoolsver} wheel pip install ${module}*.whl -pip install pytest\<5 +pip install "-r${DIR}/test-requirements.txt" mkdir not-${module} pushd not-${module} # shellcheck disable=SC2086 diff --git a/requirements.txt b/requirements.txt index de7919c..9eadc1f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ schema-salad >= 5.0.20200220195218, < 9 junit-xml >= 1.8 pytest < 7 +defusedxml diff --git a/setup.cfg b/setup.cfg index 6c900c5..aae8e39 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,10 +1,14 @@ [flake8] ignore = E124,E128,E129,E201,E202,E225,E226,E231,E265,E271,E302,E303,F401,E402,E501,W503,E731,F811,F821,F841 - -[easy_install] - -[tool:pytest] -testpaths = cwltest/tests +max-line-length = 88 +extend-ignore = E203, W503 [aliases] test=pytest + +[tool:isort] +multi_line_output = 3 +include_trailing_comma = True +force_grid_wrap = 0 +use_parentheses = True +line_length = 88 diff --git a/setup.py b/setup.py index a98125b..bb098fb 100644 --- a/setup.py +++ b/setup.py @@ -15,15 +15,19 @@ except ImportError: tagger = egg_info_cmd.egg_info -install_requires = ["schema-salad >= 5.0.20200220195218, < 9", "junit-xml >= 1.8"] +install_requires = [ + "schema-salad >= 5.0.20200220195218, < 9", + "junit-xml >= 1.8", + "defusedxml", +] needs_pytest = {"pytest", "test", "ptr"}.intersection(sys.argv) -pytest_runner = ["pytest < 6", "pytest-runner < 5"] if needs_pytest else [] +pytest_runner = ["pytest < 7", "pytest-runner"] if needs_pytest else [] setup( name="cwltest", - version="2.1", - description="Common workflow language testing framework", + version="2.2", # update the VERSION prefix in the Makefile as well 🙂 + description="Common Workflow Language testing framework", long_description=open(README).read(), long_description_content_type="text/x-rst", author="Common workflow language working group", @@ -31,12 +35,13 @@ url="https://github.com/common-workflow-language/cwltest", download_url="https://github.com/common-workflow-language/cwltest", license="Apache 2.0", + python_requires=">=3.6, <4", + setup_requires=[] + pytest_runner, packages=["cwltest", "cwltest.tests"], - package_data={"cwltest.tests": ["test-data/*"]}, + package_data={"cwltest": ["py.typed"], "cwltest.tests": ["test-data/*"]}, include_package_data=True, install_requires=install_requires, test_suite="tests", - setup_requires=[] + pytest_runner, tests_require=["pytest<7"], entry_points={ "console_scripts": [ @@ -46,5 +51,16 @@ }, zip_safe=True, cmdclass={"egg_info": tagger}, - python_requires=">=3.5, <4", + classifiers=[ + "Environment :: Console", + "License :: OSI Approved :: Apache Software License", + "Operating System :: POSIX", + "Operating System :: MacOS :: MacOS X", + "Development Status :: 5 - Production/Stable", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Typing :: Typed", + ], ) diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 0000000..fb43315 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,3 @@ +pytest >= 6.2, < 6.3 +pytest-cov +pytest-xdist diff --git a/tox.ini b/tox.ini index 179e640..c0f3f1a 100644 --- a/tox.ini +++ b/tox.ini @@ -1,65 +1,78 @@ [tox] envlist = - py{36,37,38}-lint, - py{35,36,37,38}-unit, - py{35,36,37,38}-mypy, - py37-pipconflictchecker, - py37-lint-readme, - py37-pydocstyle + py{36,37,38,39}-lint, + py{36,37,38,39}-unit, + py{36,37,38,39}-bandit, + py{36,37,38,39}-mypy, + py39-pipconflictchecker, + py39-lint-readme, + py39-pydocstyle skipsdist = True skip_missing_interpreters = True -[travis] -os = - linux: py35-{unit,mypy}, py{36,38}-{lint,unit,mypy}, py37-{unit,mypy,pipconflictchecker,lint-readme,pydocstyle} - osx: py{35,36,38}-{unit,mypy}, py37-{unit,mypy} +[pytest] +addopts=-n auto --pyargs cwltest +testpaths = cwltest/tests + +[gh-actions] python = - 3.4: py34 - 3.5: py35 3.6: py36 3.7: py37 3.8: py38 + 3.9: py39 [testenv] +description = + py{36,37,38,39}-unit: Run the unit tests + py{36,37,38,39}-lint: Lint the Python code + py{36,37,38,39}-bandit: Search for common security issues + py{36,37,38,39}-mypy: Check for type safety + py39-pydocstyle: docstring style checker + py39-lint-readme: Lint the README.rst->.md conversion + passenv = CI - TRAVIS - TRAVIS_* + GITHUB_* deps = - -rrequirements.txt - py{35,36,37,38}-unit: codecov - py{35,36,37,38}-unit: pytest-xdist - py{35,36,37,38}-unit: pytest-cov - py{36,37,38}-lint: flake8 - py{35,36,37,38}-mypy: mypy==0.782 + py{36,37,38,39}-{unit,lint,bandit,mypy}: -rrequirements.txt + py{36,37,38,39}-{unit,mypy}: -rtest-requirements.txt + py{36,37,38,39}-lint: flake8-bugbear + py{36,37,38,39}-lint: black + py{36,37,38,39}-bandit: bandit + py{36,37,38,39}-mypy: -rmypy_requirements.txt setenv = - py{35,36,37,38}-unit: LC_ALL = C + py{36,37,38,39}-unit: LC_ALL = C.UTF-8 commands = - py{35,36,37,38}-unit: python -m pip install -U pip setuptools wheel - py{35,36,37,38}-unit: python -m pip install -e . - py{35,36,37,38}-unit: coverage run --parallel-mode -m pytest --strict {posargs} - py{35,36,37,38}-unit: coverage combine - py{35,36,37,38}-unit: coverage report - py{35,36,37,38}-unit: coverage xml - py{35,36,37,38}-unit: codecov --file coverage.xml - py{36,37,38}-lint: flake8 cwltest setup.py - py{35,36,37,38}-mypy: make mypy + py{36,37,38,39}-unit: python -m pip install -U pip setuptools wheel + py{36,37,38,39}-unit: make coverage-report coverage.xml PYTEST_EXTRA={posargs} + py{36,37,38,39}-bandit: bandit --recursive cwltest + py{36,37,38,39}-lint: make flake8 + py{36,37,38,39}-lint: make format-check + py{36,37,38,39}-mypy: make mypy whitelist_externals = - py{36,37,38}-lint: flake8 - py{35,36,37,38}-mypy: make + py{36,37,38,39}-lint: flake8 + py{36,37,38,39}-lint: black + py{36,37,38,39}-{mypy,shellcheck,lint,unit}: make + +[testenv:py39-pydocstyle] +whitelist_externals = make +commands = make diff_pydocstyle_report +deps = + pydocstyle + diff-cover -[testenv:py37-pipconflictchecker] +[testenv:py39-pipconflictchecker] commands = pipconflictchecker whitelist_externals = pipconflictchecker deps = pip-conflict-checker pip==9.0.3 -[testenv:py37-lint-readme] +[testenv:py39-lint-readme] commands = python setup.py sdist python setup.py bdist_wheel @@ -68,10 +81,3 @@ deps = twine wheel readme_renderer[md] - -[testenv:py37-pydocstyle] -whitelist_externals = make -commands = make diff_pydocstyle_report -deps = - pydocstyle - diff-cover diff --git a/travis/os_install.sh b/travis/os_install.sh deleted file mode 100644 index 1336699..0000000 --- a/travis/os_install.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -if [[ $TRAVIS_OS_NAME == 'linux' ]]; then - echo No special install needed on Linux - #wget -O- http://neuro.debian.net/lists/trusty.us-nh.full | sudo tee /etc/apt/sources.list.d/neurodebian.sources.list; - #sudo apt-key add .travis.singularity_key.txt; - #sudo apt-get update; - #sudo apt-get install -y singularity-container; -elif [[ $TRAVIS_OS_NAME == "osx" ]]; then - pyenv install $PYENV_VERSION -s; - eval "$(pyenv init -)"; - pyenv global $PYENV_VERSION; - pip install -U virtualenv; - VIRTUAL_ENV="$HOME/ve-pyenv-$PYENV_VERSION"; - virtualenv -p "$(which python)" ${VIRTUALENV_EXTRA_ARGS:-} "$VIRTUAL_ENV"; - source "$VIRTUAL_ENV/bin/activate"; -fi diff --git a/typeshed/2and3/avro/__init__.pyi b/typeshed/avro/__init__.pyi similarity index 100% rename from typeshed/2and3/avro/__init__.pyi rename to typeshed/avro/__init__.pyi diff --git a/typeshed/2and3/avro/schema.pyi b/typeshed/avro/schema.pyi similarity index 100% rename from typeshed/2and3/avro/schema.pyi rename to typeshed/avro/schema.pyi diff --git a/typeshed/2and3/cachecontrol/__init__.pyi b/typeshed/cachecontrol/__init__.pyi similarity index 100% rename from typeshed/2and3/cachecontrol/__init__.pyi rename to typeshed/cachecontrol/__init__.pyi diff --git a/typeshed/2and3/cachecontrol/adapter.pyi b/typeshed/cachecontrol/adapter.pyi similarity index 100% rename from typeshed/2and3/cachecontrol/adapter.pyi rename to typeshed/cachecontrol/adapter.pyi diff --git a/typeshed/2and3/cachecontrol/cache.pyi b/typeshed/cachecontrol/cache.pyi similarity index 100% rename from typeshed/2and3/cachecontrol/cache.pyi rename to typeshed/cachecontrol/cache.pyi diff --git a/typeshed/2and3/cachecontrol/caches/__init__.pyi b/typeshed/cachecontrol/caches/__init__.pyi similarity index 100% rename from typeshed/2and3/cachecontrol/caches/__init__.pyi rename to typeshed/cachecontrol/caches/__init__.pyi diff --git a/typeshed/2and3/cachecontrol/caches/file_cache.pyi b/typeshed/cachecontrol/caches/file_cache.pyi similarity index 100% rename from typeshed/2and3/cachecontrol/caches/file_cache.pyi rename to typeshed/cachecontrol/caches/file_cache.pyi diff --git a/typeshed/2and3/cachecontrol/compat.pyi b/typeshed/cachecontrol/compat.pyi similarity index 100% rename from typeshed/2and3/cachecontrol/compat.pyi rename to typeshed/cachecontrol/compat.pyi diff --git a/typeshed/2and3/cachecontrol/controller.pyi b/typeshed/cachecontrol/controller.pyi similarity index 100% rename from typeshed/2and3/cachecontrol/controller.pyi rename to typeshed/cachecontrol/controller.pyi diff --git a/typeshed/2and3/cachecontrol/filewrapper.pyi b/typeshed/cachecontrol/filewrapper.pyi similarity index 100% rename from typeshed/2and3/cachecontrol/filewrapper.pyi rename to typeshed/cachecontrol/filewrapper.pyi diff --git a/typeshed/2and3/cachecontrol/serialize.pyi b/typeshed/cachecontrol/serialize.pyi similarity index 100% rename from typeshed/2and3/cachecontrol/serialize.pyi rename to typeshed/cachecontrol/serialize.pyi diff --git a/typeshed/2and3/cachecontrol/wrapper.pyi b/typeshed/cachecontrol/wrapper.pyi similarity index 100% rename from typeshed/2and3/cachecontrol/wrapper.pyi rename to typeshed/cachecontrol/wrapper.pyi diff --git a/typeshed/2and3/ruamel/__init__.py b/typeshed/future/__init__.pyi similarity index 100% rename from typeshed/2and3/ruamel/__init__.py rename to typeshed/future/__init__.pyi diff --git a/typeshed/2and3/future/utils/__init__.pyi b/typeshed/future/utils/__init__.pyi similarity index 100% rename from typeshed/2and3/future/utils/__init__.pyi rename to typeshed/future/utils/__init__.pyi diff --git a/typeshed/2and3/galaxy/__init__.pyi b/typeshed/galaxy/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/__init__.pyi rename to typeshed/galaxy/__init__.pyi diff --git a/typeshed/2and3/galaxy/exceptions/__init__.pyi b/typeshed/galaxy/exceptions/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/exceptions/__init__.pyi rename to typeshed/galaxy/exceptions/__init__.pyi diff --git a/typeshed/2and3/galaxy/exceptions/error_codes.pyi b/typeshed/galaxy/exceptions/error_codes.pyi similarity index 100% rename from typeshed/2and3/galaxy/exceptions/error_codes.pyi rename to typeshed/galaxy/exceptions/error_codes.pyi diff --git a/typeshed/2and3/galaxy/jobs/__init__.pyi b/typeshed/galaxy/jobs/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/__init__.pyi rename to typeshed/galaxy/jobs/__init__.pyi diff --git a/typeshed/2and3/galaxy/jobs/metrics/__init__.pyi b/typeshed/galaxy/jobs/metrics/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/metrics/__init__.pyi rename to typeshed/galaxy/jobs/metrics/__init__.pyi diff --git a/typeshed/2and3/galaxy/jobs/metrics/collectl/__init__.pyi b/typeshed/galaxy/jobs/metrics/collectl/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/metrics/collectl/__init__.pyi rename to typeshed/galaxy/jobs/metrics/collectl/__init__.pyi diff --git a/typeshed/2and3/galaxy/jobs/metrics/collectl/cli.pyi b/typeshed/galaxy/jobs/metrics/collectl/cli.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/metrics/collectl/cli.pyi rename to typeshed/galaxy/jobs/metrics/collectl/cli.pyi diff --git a/typeshed/2and3/galaxy/jobs/metrics/collectl/processes.pyi b/typeshed/galaxy/jobs/metrics/collectl/processes.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/metrics/collectl/processes.pyi rename to typeshed/galaxy/jobs/metrics/collectl/processes.pyi diff --git a/typeshed/2and3/galaxy/jobs/metrics/collectl/stats.pyi b/typeshed/galaxy/jobs/metrics/collectl/stats.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/metrics/collectl/stats.pyi rename to typeshed/galaxy/jobs/metrics/collectl/stats.pyi diff --git a/typeshed/2and3/galaxy/jobs/metrics/collectl/subsystems.pyi b/typeshed/galaxy/jobs/metrics/collectl/subsystems.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/metrics/collectl/subsystems.pyi rename to typeshed/galaxy/jobs/metrics/collectl/subsystems.pyi diff --git a/typeshed/2and3/galaxy/jobs/metrics/formatting.pyi b/typeshed/galaxy/jobs/metrics/formatting.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/metrics/formatting.pyi rename to typeshed/galaxy/jobs/metrics/formatting.pyi diff --git a/typeshed/2and3/galaxy/jobs/metrics/instrumenters/__init__.pyi b/typeshed/galaxy/jobs/metrics/instrumenters/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/metrics/instrumenters/__init__.pyi rename to typeshed/galaxy/jobs/metrics/instrumenters/__init__.pyi diff --git a/typeshed/2and3/galaxy/jobs/metrics/instrumenters/collectl.pyi b/typeshed/galaxy/jobs/metrics/instrumenters/collectl.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/metrics/instrumenters/collectl.pyi rename to typeshed/galaxy/jobs/metrics/instrumenters/collectl.pyi diff --git a/typeshed/2and3/galaxy/jobs/metrics/instrumenters/core.pyi b/typeshed/galaxy/jobs/metrics/instrumenters/core.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/metrics/instrumenters/core.pyi rename to typeshed/galaxy/jobs/metrics/instrumenters/core.pyi diff --git a/typeshed/2and3/galaxy/jobs/metrics/instrumenters/cpuinfo.pyi b/typeshed/galaxy/jobs/metrics/instrumenters/cpuinfo.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/metrics/instrumenters/cpuinfo.pyi rename to typeshed/galaxy/jobs/metrics/instrumenters/cpuinfo.pyi diff --git a/typeshed/2and3/galaxy/jobs/metrics/instrumenters/env.pyi b/typeshed/galaxy/jobs/metrics/instrumenters/env.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/metrics/instrumenters/env.pyi rename to typeshed/galaxy/jobs/metrics/instrumenters/env.pyi diff --git a/typeshed/2and3/galaxy/jobs/metrics/instrumenters/meminfo.pyi b/typeshed/galaxy/jobs/metrics/instrumenters/meminfo.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/metrics/instrumenters/meminfo.pyi rename to typeshed/galaxy/jobs/metrics/instrumenters/meminfo.pyi diff --git a/typeshed/2and3/galaxy/jobs/metrics/instrumenters/uname.pyi b/typeshed/galaxy/jobs/metrics/instrumenters/uname.pyi similarity index 100% rename from typeshed/2and3/galaxy/jobs/metrics/instrumenters/uname.pyi rename to typeshed/galaxy/jobs/metrics/instrumenters/uname.pyi diff --git a/typeshed/2and3/galaxy/objectstore/__init__.pyi b/typeshed/galaxy/objectstore/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/objectstore/__init__.pyi rename to typeshed/galaxy/objectstore/__init__.pyi diff --git a/typeshed/2and3/galaxy/objectstore/azure_blob.pyi b/typeshed/galaxy/objectstore/azure_blob.pyi similarity index 100% rename from typeshed/2and3/galaxy/objectstore/azure_blob.pyi rename to typeshed/galaxy/objectstore/azure_blob.pyi diff --git a/typeshed/2and3/galaxy/objectstore/pulsar.pyi b/typeshed/galaxy/objectstore/pulsar.pyi similarity index 100% rename from typeshed/2and3/galaxy/objectstore/pulsar.pyi rename to typeshed/galaxy/objectstore/pulsar.pyi diff --git a/typeshed/2and3/galaxy/objectstore/rods.pyi b/typeshed/galaxy/objectstore/rods.pyi similarity index 100% rename from typeshed/2and3/galaxy/objectstore/rods.pyi rename to typeshed/galaxy/objectstore/rods.pyi diff --git a/typeshed/2and3/galaxy/objectstore/s3.pyi b/typeshed/galaxy/objectstore/s3.pyi similarity index 100% rename from typeshed/2and3/galaxy/objectstore/s3.pyi rename to typeshed/galaxy/objectstore/s3.pyi diff --git a/typeshed/2and3/galaxy/objectstore/s3_multipart_upload.pyi b/typeshed/galaxy/objectstore/s3_multipart_upload.pyi similarity index 100% rename from typeshed/2and3/galaxy/objectstore/s3_multipart_upload.pyi rename to typeshed/galaxy/objectstore/s3_multipart_upload.pyi diff --git a/typeshed/2and3/galaxy/tools/__init__.pyi b/typeshed/galaxy/tools/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/__init__.pyi rename to typeshed/galaxy/tools/__init__.pyi diff --git a/typeshed/2and3/galaxy/tools/cwl/__init__.pyi b/typeshed/galaxy/tools/cwl/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/cwl/__init__.pyi rename to typeshed/galaxy/tools/cwl/__init__.pyi diff --git a/typeshed/2and3/galaxy/tools/cwl/cwltool_deps.pyi b/typeshed/galaxy/tools/cwl/cwltool_deps.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/cwl/cwltool_deps.pyi rename to typeshed/galaxy/tools/cwl/cwltool_deps.pyi diff --git a/typeshed/2and3/galaxy/tools/cwl/parser.pyi b/typeshed/galaxy/tools/cwl/parser.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/cwl/parser.pyi rename to typeshed/galaxy/tools/cwl/parser.pyi diff --git a/typeshed/2and3/galaxy/tools/cwl/representation.pyi b/typeshed/galaxy/tools/cwl/representation.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/cwl/representation.pyi rename to typeshed/galaxy/tools/cwl/representation.pyi diff --git a/typeshed/2and3/galaxy/tools/cwl/runtime_actions.pyi b/typeshed/galaxy/tools/cwl/runtime_actions.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/cwl/runtime_actions.pyi rename to typeshed/galaxy/tools/cwl/runtime_actions.pyi diff --git a/typeshed/2and3/galaxy/tools/cwl/schema.pyi b/typeshed/galaxy/tools/cwl/schema.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/cwl/schema.pyi rename to typeshed/galaxy/tools/cwl/schema.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/__init__.pyi b/typeshed/galaxy/tools/deps/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/__init__.pyi rename to typeshed/galaxy/tools/deps/__init__.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/brew_exts.pyi b/typeshed/galaxy/tools/deps/brew_exts.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/brew_exts.pyi rename to typeshed/galaxy/tools/deps/brew_exts.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/brew_util.pyi b/typeshed/galaxy/tools/deps/brew_util.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/brew_util.pyi rename to typeshed/galaxy/tools/deps/brew_util.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/commands.pyi b/typeshed/galaxy/tools/deps/commands.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/commands.pyi rename to typeshed/galaxy/tools/deps/commands.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/conda_compat.pyi b/typeshed/galaxy/tools/deps/conda_compat.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/conda_compat.pyi rename to typeshed/galaxy/tools/deps/conda_compat.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/conda_util.pyi b/typeshed/galaxy/tools/deps/conda_util.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/conda_util.pyi rename to typeshed/galaxy/tools/deps/conda_util.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/container_resolvers/__init__.pyi b/typeshed/galaxy/tools/deps/container_resolvers/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/container_resolvers/__init__.pyi rename to typeshed/galaxy/tools/deps/container_resolvers/__init__.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/container_resolvers/explicit.pyi b/typeshed/galaxy/tools/deps/container_resolvers/explicit.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/container_resolvers/explicit.pyi rename to typeshed/galaxy/tools/deps/container_resolvers/explicit.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/container_resolvers/mulled.pyi b/typeshed/galaxy/tools/deps/container_resolvers/mulled.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/container_resolvers/mulled.pyi rename to typeshed/galaxy/tools/deps/container_resolvers/mulled.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/containers.pyi b/typeshed/galaxy/tools/deps/containers.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/containers.pyi rename to typeshed/galaxy/tools/deps/containers.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/dependencies.pyi b/typeshed/galaxy/tools/deps/dependencies.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/dependencies.pyi rename to typeshed/galaxy/tools/deps/dependencies.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/docker_util.pyi b/typeshed/galaxy/tools/deps/docker_util.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/docker_util.pyi rename to typeshed/galaxy/tools/deps/docker_util.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/dockerfiles.pyi b/typeshed/galaxy/tools/deps/dockerfiles.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/dockerfiles.pyi rename to typeshed/galaxy/tools/deps/dockerfiles.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/installable.pyi b/typeshed/galaxy/tools/deps/installable.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/installable.pyi rename to typeshed/galaxy/tools/deps/installable.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/mulled/__init__.pyi b/typeshed/galaxy/tools/deps/mulled/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/mulled/__init__.pyi rename to typeshed/galaxy/tools/deps/mulled/__init__.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/mulled/_cli.pyi b/typeshed/galaxy/tools/deps/mulled/_cli.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/mulled/_cli.pyi rename to typeshed/galaxy/tools/deps/mulled/_cli.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/mulled/mulled_build.pyi b/typeshed/galaxy/tools/deps/mulled/mulled_build.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/mulled/mulled_build.pyi rename to typeshed/galaxy/tools/deps/mulled/mulled_build.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/mulled/mulled_build_channel.pyi b/typeshed/galaxy/tools/deps/mulled/mulled_build_channel.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/mulled/mulled_build_channel.pyi rename to typeshed/galaxy/tools/deps/mulled/mulled_build_channel.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/mulled/mulled_build_files.pyi b/typeshed/galaxy/tools/deps/mulled/mulled_build_files.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/mulled/mulled_build_files.pyi rename to typeshed/galaxy/tools/deps/mulled/mulled_build_files.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/mulled/mulled_build_tool.pyi b/typeshed/galaxy/tools/deps/mulled/mulled_build_tool.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/mulled/mulled_build_tool.pyi rename to typeshed/galaxy/tools/deps/mulled/mulled_build_tool.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/mulled/mulled_search.pyi b/typeshed/galaxy/tools/deps/mulled/mulled_search.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/mulled/mulled_search.pyi rename to typeshed/galaxy/tools/deps/mulled/mulled_search.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/mulled/util.pyi b/typeshed/galaxy/tools/deps/mulled/util.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/mulled/util.pyi rename to typeshed/galaxy/tools/deps/mulled/util.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/requirements.pyi b/typeshed/galaxy/tools/deps/requirements.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/requirements.pyi rename to typeshed/galaxy/tools/deps/requirements.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/resolvers/__init__.pyi b/typeshed/galaxy/tools/deps/resolvers/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/resolvers/__init__.pyi rename to typeshed/galaxy/tools/deps/resolvers/__init__.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/resolvers/brewed_tool_shed_packages.pyi b/typeshed/galaxy/tools/deps/resolvers/brewed_tool_shed_packages.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/resolvers/brewed_tool_shed_packages.pyi rename to typeshed/galaxy/tools/deps/resolvers/brewed_tool_shed_packages.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/resolvers/conda.pyi b/typeshed/galaxy/tools/deps/resolvers/conda.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/resolvers/conda.pyi rename to typeshed/galaxy/tools/deps/resolvers/conda.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/resolvers/galaxy_packages.pyi b/typeshed/galaxy/tools/deps/resolvers/galaxy_packages.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/resolvers/galaxy_packages.pyi rename to typeshed/galaxy/tools/deps/resolvers/galaxy_packages.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/resolvers/homebrew.pyi b/typeshed/galaxy/tools/deps/resolvers/homebrew.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/resolvers/homebrew.pyi rename to typeshed/galaxy/tools/deps/resolvers/homebrew.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/resolvers/modules.pyi b/typeshed/galaxy/tools/deps/resolvers/modules.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/resolvers/modules.pyi rename to typeshed/galaxy/tools/deps/resolvers/modules.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/resolvers/resolver_mixins.pyi b/typeshed/galaxy/tools/deps/resolvers/resolver_mixins.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/resolvers/resolver_mixins.pyi rename to typeshed/galaxy/tools/deps/resolvers/resolver_mixins.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/resolvers/tool_shed_packages.pyi b/typeshed/galaxy/tools/deps/resolvers/tool_shed_packages.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/resolvers/tool_shed_packages.pyi rename to typeshed/galaxy/tools/deps/resolvers/tool_shed_packages.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/resolvers/unlinked_tool_shed_packages.pyi b/typeshed/galaxy/tools/deps/resolvers/unlinked_tool_shed_packages.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/resolvers/unlinked_tool_shed_packages.pyi rename to typeshed/galaxy/tools/deps/resolvers/unlinked_tool_shed_packages.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/singularity_util.pyi b/typeshed/galaxy/tools/deps/singularity_util.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/singularity_util.pyi rename to typeshed/galaxy/tools/deps/singularity_util.pyi diff --git a/typeshed/2and3/galaxy/tools/deps/views.pyi b/typeshed/galaxy/tools/deps/views.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/deps/views.pyi rename to typeshed/galaxy/tools/deps/views.pyi diff --git a/typeshed/2and3/galaxy/tools/fetcher.pyi b/typeshed/galaxy/tools/fetcher.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/fetcher.pyi rename to typeshed/galaxy/tools/fetcher.pyi diff --git a/typeshed/2and3/galaxy/tools/lint.pyi b/typeshed/galaxy/tools/lint.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/lint.pyi rename to typeshed/galaxy/tools/lint.pyi diff --git a/typeshed/2and3/galaxy/tools/lint_util.pyi b/typeshed/galaxy/tools/lint_util.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/lint_util.pyi rename to typeshed/galaxy/tools/lint_util.pyi diff --git a/typeshed/2and3/galaxy/tools/linters/__init__.pyi b/typeshed/galaxy/tools/linters/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/linters/__init__.pyi rename to typeshed/galaxy/tools/linters/__init__.pyi diff --git a/typeshed/2and3/galaxy/tools/linters/citations.pyi b/typeshed/galaxy/tools/linters/citations.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/linters/citations.pyi rename to typeshed/galaxy/tools/linters/citations.pyi diff --git a/typeshed/2and3/galaxy/tools/linters/command.pyi b/typeshed/galaxy/tools/linters/command.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/linters/command.pyi rename to typeshed/galaxy/tools/linters/command.pyi diff --git a/typeshed/2and3/galaxy/tools/linters/cwl.pyi b/typeshed/galaxy/tools/linters/cwl.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/linters/cwl.pyi rename to typeshed/galaxy/tools/linters/cwl.pyi diff --git a/typeshed/2and3/galaxy/tools/linters/general.pyi b/typeshed/galaxy/tools/linters/general.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/linters/general.pyi rename to typeshed/galaxy/tools/linters/general.pyi diff --git a/typeshed/2and3/galaxy/tools/linters/help.pyi b/typeshed/galaxy/tools/linters/help.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/linters/help.pyi rename to typeshed/galaxy/tools/linters/help.pyi diff --git a/typeshed/2and3/galaxy/tools/linters/inputs.pyi b/typeshed/galaxy/tools/linters/inputs.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/linters/inputs.pyi rename to typeshed/galaxy/tools/linters/inputs.pyi diff --git a/typeshed/2and3/galaxy/tools/linters/outputs.pyi b/typeshed/galaxy/tools/linters/outputs.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/linters/outputs.pyi rename to typeshed/galaxy/tools/linters/outputs.pyi diff --git a/typeshed/2and3/galaxy/tools/linters/stdio.pyi b/typeshed/galaxy/tools/linters/stdio.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/linters/stdio.pyi rename to typeshed/galaxy/tools/linters/stdio.pyi diff --git a/typeshed/2and3/galaxy/tools/linters/tests.pyi b/typeshed/galaxy/tools/linters/tests.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/linters/tests.pyi rename to typeshed/galaxy/tools/linters/tests.pyi diff --git a/typeshed/2and3/galaxy/tools/linters/xml_order.pyi b/typeshed/galaxy/tools/linters/xml_order.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/linters/xml_order.pyi rename to typeshed/galaxy/tools/linters/xml_order.pyi diff --git a/typeshed/2and3/galaxy/tools/loader.pyi b/typeshed/galaxy/tools/loader.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/loader.pyi rename to typeshed/galaxy/tools/loader.pyi diff --git a/typeshed/2and3/galaxy/tools/loader_directory.pyi b/typeshed/galaxy/tools/loader_directory.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/loader_directory.pyi rename to typeshed/galaxy/tools/loader_directory.pyi diff --git a/typeshed/2and3/galaxy/tools/locations/__init__.pyi b/typeshed/galaxy/tools/locations/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/locations/__init__.pyi rename to typeshed/galaxy/tools/locations/__init__.pyi diff --git a/typeshed/2and3/galaxy/tools/locations/dockstore.pyi b/typeshed/galaxy/tools/locations/dockstore.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/locations/dockstore.pyi rename to typeshed/galaxy/tools/locations/dockstore.pyi diff --git a/typeshed/2and3/galaxy/tools/locations/file.pyi b/typeshed/galaxy/tools/locations/file.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/locations/file.pyi rename to typeshed/galaxy/tools/locations/file.pyi diff --git a/typeshed/2and3/galaxy/tools/locations/http.pyi b/typeshed/galaxy/tools/locations/http.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/locations/http.pyi rename to typeshed/galaxy/tools/locations/http.pyi diff --git a/typeshed/2and3/galaxy/tools/parser/__init__.pyi b/typeshed/galaxy/tools/parser/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/parser/__init__.pyi rename to typeshed/galaxy/tools/parser/__init__.pyi diff --git a/typeshed/2and3/galaxy/tools/parser/cwl.pyi b/typeshed/galaxy/tools/parser/cwl.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/parser/cwl.pyi rename to typeshed/galaxy/tools/parser/cwl.pyi diff --git a/typeshed/2and3/galaxy/tools/parser/factory.pyi b/typeshed/galaxy/tools/parser/factory.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/parser/factory.pyi rename to typeshed/galaxy/tools/parser/factory.pyi diff --git a/typeshed/2and3/galaxy/tools/parser/interface.pyi b/typeshed/galaxy/tools/parser/interface.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/parser/interface.pyi rename to typeshed/galaxy/tools/parser/interface.pyi diff --git a/typeshed/2and3/galaxy/tools/parser/output_actions.pyi b/typeshed/galaxy/tools/parser/output_actions.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/parser/output_actions.pyi rename to typeshed/galaxy/tools/parser/output_actions.pyi diff --git a/typeshed/2and3/galaxy/tools/parser/output_collection_def.pyi b/typeshed/galaxy/tools/parser/output_collection_def.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/parser/output_collection_def.pyi rename to typeshed/galaxy/tools/parser/output_collection_def.pyi diff --git a/typeshed/2and3/galaxy/tools/parser/output_objects.pyi b/typeshed/galaxy/tools/parser/output_objects.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/parser/output_objects.pyi rename to typeshed/galaxy/tools/parser/output_objects.pyi diff --git a/typeshed/2and3/galaxy/tools/parser/util.pyi b/typeshed/galaxy/tools/parser/util.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/parser/util.pyi rename to typeshed/galaxy/tools/parser/util.pyi diff --git a/typeshed/2and3/galaxy/tools/parser/xml.pyi b/typeshed/galaxy/tools/parser/xml.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/parser/xml.pyi rename to typeshed/galaxy/tools/parser/xml.pyi diff --git a/typeshed/2and3/galaxy/tools/parser/yaml.pyi b/typeshed/galaxy/tools/parser/yaml.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/parser/yaml.pyi rename to typeshed/galaxy/tools/parser/yaml.pyi diff --git a/typeshed/2and3/galaxy/tools/verify/__init__.pyi b/typeshed/galaxy/tools/verify/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/verify/__init__.pyi rename to typeshed/galaxy/tools/verify/__init__.pyi diff --git a/typeshed/2and3/galaxy/tools/verify/asserts/__init__.pyi b/typeshed/galaxy/tools/verify/asserts/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/verify/asserts/__init__.pyi rename to typeshed/galaxy/tools/verify/asserts/__init__.pyi diff --git a/typeshed/2and3/galaxy/tools/verify/asserts/tabular.pyi b/typeshed/galaxy/tools/verify/asserts/tabular.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/verify/asserts/tabular.pyi rename to typeshed/galaxy/tools/verify/asserts/tabular.pyi diff --git a/typeshed/2and3/galaxy/tools/verify/asserts/text.pyi b/typeshed/galaxy/tools/verify/asserts/text.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/verify/asserts/text.pyi rename to typeshed/galaxy/tools/verify/asserts/text.pyi diff --git a/typeshed/2and3/galaxy/tools/verify/asserts/xml.pyi b/typeshed/galaxy/tools/verify/asserts/xml.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/verify/asserts/xml.pyi rename to typeshed/galaxy/tools/verify/asserts/xml.pyi diff --git a/typeshed/2and3/galaxy/tools/verify/test_data.pyi b/typeshed/galaxy/tools/verify/test_data.pyi similarity index 100% rename from typeshed/2and3/galaxy/tools/verify/test_data.pyi rename to typeshed/galaxy/tools/verify/test_data.pyi diff --git a/typeshed/2and3/galaxy/util/__init__.pyi b/typeshed/galaxy/util/__init__.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/__init__.pyi rename to typeshed/galaxy/util/__init__.pyi diff --git a/typeshed/2and3/galaxy/util/aliaspickler.pyi b/typeshed/galaxy/util/aliaspickler.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/aliaspickler.pyi rename to typeshed/galaxy/util/aliaspickler.pyi diff --git a/typeshed/2and3/galaxy/util/bunch.pyi b/typeshed/galaxy/util/bunch.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/bunch.pyi rename to typeshed/galaxy/util/bunch.pyi diff --git a/typeshed/2and3/galaxy/util/checkers.pyi b/typeshed/galaxy/util/checkers.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/checkers.pyi rename to typeshed/galaxy/util/checkers.pyi diff --git a/typeshed/2and3/galaxy/util/compression_utils.pyi b/typeshed/galaxy/util/compression_utils.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/compression_utils.pyi rename to typeshed/galaxy/util/compression_utils.pyi diff --git a/typeshed/2and3/galaxy/util/dictifiable.pyi b/typeshed/galaxy/util/dictifiable.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/dictifiable.pyi rename to typeshed/galaxy/util/dictifiable.pyi diff --git a/typeshed/2and3/galaxy/util/expressions.pyi b/typeshed/galaxy/util/expressions.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/expressions.pyi rename to typeshed/galaxy/util/expressions.pyi diff --git a/typeshed/2and3/galaxy/util/filelock.pyi b/typeshed/galaxy/util/filelock.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/filelock.pyi rename to typeshed/galaxy/util/filelock.pyi diff --git a/typeshed/2and3/galaxy/util/hash_util.pyi b/typeshed/galaxy/util/hash_util.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/hash_util.pyi rename to typeshed/galaxy/util/hash_util.pyi diff --git a/typeshed/2and3/galaxy/util/heartbeat.pyi b/typeshed/galaxy/util/heartbeat.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/heartbeat.pyi rename to typeshed/galaxy/util/heartbeat.pyi diff --git a/typeshed/2and3/galaxy/util/image_util.pyi b/typeshed/galaxy/util/image_util.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/image_util.pyi rename to typeshed/galaxy/util/image_util.pyi diff --git a/typeshed/2and3/galaxy/util/inflection.pyi b/typeshed/galaxy/util/inflection.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/inflection.pyi rename to typeshed/galaxy/util/inflection.pyi diff --git a/typeshed/2and3/galaxy/util/json.pyi b/typeshed/galaxy/util/json.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/json.pyi rename to typeshed/galaxy/util/json.pyi diff --git a/typeshed/2and3/galaxy/util/lazy_process.pyi b/typeshed/galaxy/util/lazy_process.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/lazy_process.pyi rename to typeshed/galaxy/util/lazy_process.pyi diff --git a/typeshed/2and3/galaxy/util/object_wrapper.pyi b/typeshed/galaxy/util/object_wrapper.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/object_wrapper.pyi rename to typeshed/galaxy/util/object_wrapper.pyi diff --git a/typeshed/2and3/galaxy/util/odict.pyi b/typeshed/galaxy/util/odict.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/odict.pyi rename to typeshed/galaxy/util/odict.pyi diff --git a/typeshed/2and3/galaxy/util/oset.pyi b/typeshed/galaxy/util/oset.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/oset.pyi rename to typeshed/galaxy/util/oset.pyi diff --git a/typeshed/2and3/galaxy/util/plugin_config.pyi b/typeshed/galaxy/util/plugin_config.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/plugin_config.pyi rename to typeshed/galaxy/util/plugin_config.pyi diff --git a/typeshed/2and3/galaxy/util/properties.pyi b/typeshed/galaxy/util/properties.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/properties.pyi rename to typeshed/galaxy/util/properties.pyi diff --git a/typeshed/2and3/galaxy/util/simplegraph.pyi b/typeshed/galaxy/util/simplegraph.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/simplegraph.pyi rename to typeshed/galaxy/util/simplegraph.pyi diff --git a/typeshed/2and3/galaxy/util/sleeper.pyi b/typeshed/galaxy/util/sleeper.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/sleeper.pyi rename to typeshed/galaxy/util/sleeper.pyi diff --git a/typeshed/2and3/galaxy/util/sockets.pyi b/typeshed/galaxy/util/sockets.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/sockets.pyi rename to typeshed/galaxy/util/sockets.pyi diff --git a/typeshed/2and3/galaxy/util/specs.pyi b/typeshed/galaxy/util/specs.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/specs.pyi rename to typeshed/galaxy/util/specs.pyi diff --git a/typeshed/2and3/galaxy/util/sqlite.pyi b/typeshed/galaxy/util/sqlite.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/sqlite.pyi rename to typeshed/galaxy/util/sqlite.pyi diff --git a/typeshed/2and3/galaxy/util/submodules.pyi b/typeshed/galaxy/util/submodules.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/submodules.pyi rename to typeshed/galaxy/util/submodules.pyi diff --git a/typeshed/2and3/galaxy/util/topsort.pyi b/typeshed/galaxy/util/topsort.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/topsort.pyi rename to typeshed/galaxy/util/topsort.pyi diff --git a/typeshed/2and3/galaxy/util/xml_macros.pyi b/typeshed/galaxy/util/xml_macros.pyi similarity index 100% rename from typeshed/2and3/galaxy/util/xml_macros.pyi rename to typeshed/galaxy/util/xml_macros.pyi diff --git a/typeshed/2and3/junit_xml.pyi b/typeshed/junit_xml.pyi similarity index 100% rename from typeshed/2and3/junit_xml.pyi rename to typeshed/junit_xml.pyi diff --git a/typeshed/2and3/mistune.pyi b/typeshed/mistune.pyi similarity index 100% rename from typeshed/2and3/mistune.pyi rename to typeshed/mistune.pyi diff --git a/typeshed/2and3/rdflib/__init__.pyi b/typeshed/rdflib/__init__.pyi similarity index 100% rename from typeshed/2and3/rdflib/__init__.pyi rename to typeshed/rdflib/__init__.pyi diff --git a/typeshed/2and3/rdflib/events.pyi b/typeshed/rdflib/events.pyi similarity index 100% rename from typeshed/2and3/rdflib/events.pyi rename to typeshed/rdflib/events.pyi diff --git a/typeshed/2and3/rdflib/exceptions.pyi b/typeshed/rdflib/exceptions.pyi similarity index 100% rename from typeshed/2and3/rdflib/exceptions.pyi rename to typeshed/rdflib/exceptions.pyi diff --git a/typeshed/2and3/rdflib/graph.pyi b/typeshed/rdflib/graph.pyi similarity index 100% rename from typeshed/2and3/rdflib/graph.pyi rename to typeshed/rdflib/graph.pyi diff --git a/typeshed/2and3/rdflib/namespace.pyi b/typeshed/rdflib/namespace.pyi similarity index 100% rename from typeshed/2and3/rdflib/namespace.pyi rename to typeshed/rdflib/namespace.pyi diff --git a/typeshed/2and3/rdflib/parser.pyi b/typeshed/rdflib/parser.pyi similarity index 100% rename from typeshed/2and3/rdflib/parser.pyi rename to typeshed/rdflib/parser.pyi diff --git a/typeshed/2and3/rdflib/plugin.pyi b/typeshed/rdflib/plugin.pyi similarity index 100% rename from typeshed/2and3/rdflib/plugin.pyi rename to typeshed/rdflib/plugin.pyi diff --git a/typeshed/2and3/rdflib/plugins/__init__.pyi b/typeshed/rdflib/plugins/__init__.pyi similarity index 100% rename from typeshed/2and3/rdflib/plugins/__init__.pyi rename to typeshed/rdflib/plugins/__init__.pyi diff --git a/typeshed/2and3/rdflib/plugins/parsers/__init__.pyi b/typeshed/rdflib/plugins/parsers/__init__.pyi similarity index 100% rename from typeshed/2and3/rdflib/plugins/parsers/__init__.pyi rename to typeshed/rdflib/plugins/parsers/__init__.pyi diff --git a/typeshed/2and3/rdflib/plugins/parsers/notation3.pyi b/typeshed/rdflib/plugins/parsers/notation3.pyi similarity index 100% rename from typeshed/2and3/rdflib/plugins/parsers/notation3.pyi rename to typeshed/rdflib/plugins/parsers/notation3.pyi diff --git a/typeshed/2and3/rdflib/query.pyi b/typeshed/rdflib/query.pyi similarity index 100% rename from typeshed/2and3/rdflib/query.pyi rename to typeshed/rdflib/query.pyi diff --git a/typeshed/2and3/rdflib/serializer.pyi b/typeshed/rdflib/serializer.pyi similarity index 100% rename from typeshed/2and3/rdflib/serializer.pyi rename to typeshed/rdflib/serializer.pyi diff --git a/typeshed/2and3/rdflib/store.pyi b/typeshed/rdflib/store.pyi similarity index 100% rename from typeshed/2and3/rdflib/store.pyi rename to typeshed/rdflib/store.pyi diff --git a/typeshed/2and3/rdflib/term.pyi b/typeshed/rdflib/term.pyi similarity index 100% rename from typeshed/2and3/rdflib/term.pyi rename to typeshed/rdflib/term.pyi diff --git a/typeshed/2and3/rdflib/util.pyi b/typeshed/rdflib/util.pyi similarity index 100% rename from typeshed/2and3/rdflib/util.pyi rename to typeshed/rdflib/util.pyi diff --git a/typeshed/3/urllib/__init__.py b/typeshed/ruamel/__init__.py similarity index 100% rename from typeshed/3/urllib/__init__.py rename to typeshed/ruamel/__init__.py diff --git a/typeshed/2and3/select.pyi b/typeshed/select.pyi similarity index 100% rename from typeshed/2and3/select.pyi rename to typeshed/select.pyi diff --git a/typeshed/2and3/shellescape/__init__.pyi b/typeshed/shellescape/__init__.pyi similarity index 100% rename from typeshed/2and3/shellescape/__init__.pyi rename to typeshed/shellescape/__init__.pyi diff --git a/typeshed/2and3/shellescape/main.pyi b/typeshed/shellescape/main.pyi similarity index 100% rename from typeshed/2and3/shellescape/main.pyi rename to typeshed/shellescape/main.pyi diff --git a/typeshed/urllib/__init__.py b/typeshed/urllib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/typeshed/3/urllib/parse.pyi b/typeshed/urllib/parse.pyi similarity index 100% rename from typeshed/3/urllib/parse.pyi rename to typeshed/urllib/parse.pyi diff --git a/typeshed/3/urllib/subprocess.pyi b/typeshed/urllib/subprocess.pyi similarity index 100% rename from typeshed/3/urllib/subprocess.pyi rename to typeshed/urllib/subprocess.pyi From a1123671152b20a0d54ff089d50d0bd2b2101abb Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Wed, 1 Sep 2021 15:48:51 +0200 Subject: [PATCH 011/165] pyupgrade to 3.6+ syntax --- cwltest/__init__.py | 68 +++++++++++++++++--------------- cwltest/tests/test_categories.py | 26 ++++++++++-- cwltest/tests/test_prepare.py | 6 +-- cwltest/utils.py | 28 ++++++------- 4 files changed, 75 insertions(+), 53 deletions(-) diff --git a/cwltest/__init__.py b/cwltest/__init__.py index 33eb121..dcf9df7 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -37,12 +37,8 @@ UNSUPPORTED_FEATURE = 33 DEFAULT_TIMEOUT = 600 # 10 minutes -if sys.version_info < (3, 0): - import subprocess32 as subprocess # nosec - from pipes import quote -else: - import subprocess # nosec - from shlex import quote +import subprocess # nosec +from shlex import quote templock = threading.Lock() @@ -55,7 +51,7 @@ def prepare_test_command( cwd, # type: str verbose=False, # type: bool ): # type: (...) -> List[str] - """ Turn the test into a command line. """ + """Turn the test into a command line.""" test_command = [tool] test_command.extend(args) @@ -72,26 +68,26 @@ def prepare_test_command( outdir = tempfile.mkdtemp(prefix=os.path.abspath(os.path.curdir)) test_command.extend( [ - "--tmp-outdir-prefix={}".format(outdir), - "--tmpdir-prefix={}".format(outdir), + f"--tmp-outdir-prefix={outdir}", + f"--tmpdir-prefix={outdir}", ] ) else: outdir = tempfile.mkdtemp() - test_command.extend(["--outdir={}".format(outdir)]) + test_command.extend([f"--outdir={outdir}"]) if not verbose: test_command.extend(["--quiet"]) cwd = schema_salad.ref_resolver.file_uri(cwd) toolpath = test["tool"] if toolpath.startswith(cwd): - toolpath = toolpath[len(cwd)+1:] + toolpath = toolpath[len(cwd) + 1 :] test_command.extend([os.path.normcase(toolpath)]) jobpath = test.get("job") if jobpath: if jobpath.startswith(cwd): - jobpath = jobpath[len(cwd)+1:] + jobpath = jobpath[len(cwd) + 1 :] test_command.append(os.path.normcase(jobpath)) return test_command @@ -108,7 +104,7 @@ def run_test( global templock out = {} # type: Dict[str,Any] - outdir = outstr = outerr = u"" + outdir = outstr = outerr = "" test_command = [] # type: List[str] duration = 0.0 prefix = "" @@ -145,7 +141,13 @@ def run_test( start_time = time.time() stderr = subprocess.PIPE if not args.verbose else None - process = subprocess.Popen(test_command, stdout=subprocess.PIPE, stderr=stderr, universal_newlines=True, cwd=cwd) # nosec + process = subprocess.Popen( # nosec + test_command, + stdout=subprocess.PIPE, + stderr=stderr, + universal_newlines=True, + cwd=cwd, + ) outstr, outerr = process.communicate(timeout=timeout) return_code = process.poll() duration = time.time() - start_time @@ -167,25 +169,25 @@ def run_test( if test.get("should_fail", False): return TestResult(0, outstr, outerr, duration, args.classname) _logger.error( - u"""Test %i failed: %s""", + """Test %i failed: %s""", test_number, " ".join([quote(tc) for tc in test_command]), ) _logger.error(test.get("doc")) if err.returncode == UNSUPPORTED_FEATURE: - _logger.error(u"Does not support required feature") + _logger.error("Does not support required feature") else: - _logger.error(u"Returned non-zero") + _logger.error("Returned non-zero") _logger.error(outerr) return TestResult(1, outstr, outerr, duration, args.classname, str(err)) except (yamlscanner.ScannerError, TypeError) as err: _logger.error( - u"""Test %i failed: %s""", + """Test %i failed: %s""", test_number, - u" ".join([quote(tc) for tc in test_command]), + " ".join([quote(tc) for tc in test_command]), ) _logger.error(outstr) - _logger.error(u"Parse error %s", str(err)) + _logger.error("Parse error %s", str(err)) _logger.error(outerr) except KeyboardInterrupt: _logger.error( @@ -204,7 +206,7 @@ def run_test( return TestResult(2, outstr, outerr, timeout, args.classname, "Test timed out") finally: if process is not None and process.returncode is None: - _logger.error(u"""Terminating lingering process""") + _logger.error("""Terminating lingering process""") process.terminate() for _ in range(0, 3): time.sleep(1) @@ -217,24 +219,24 @@ def run_test( if test.get("should_fail", False): _logger.warning( - u"""Test %i failed: %s""", + """Test %i failed: %s""", test_number, - u" ".join([quote(tc) for tc in test_command]), + " ".join([quote(tc) for tc in test_command]), ) _logger.warning(test.get("doc")) - _logger.warning(u"Returned zero but it should be non-zero") + _logger.warning("Returned zero but it should be non-zero") return TestResult(1, outstr, outerr, duration, args.classname) try: compare(test.get("output"), out) except CompareFail as ex: _logger.warning( - u"""Test %i failed: %s""", + """Test %i failed: %s""", test_number, - u" ".join([quote(tc) for tc in test_command]), + " ".join([quote(tc) for tc in test_command]), ) _logger.warning(test.get("doc")) - _logger.warning(u"Compare failure %s", ex) + _logger.warning("Compare failure %s", ex) fail_message = str(ex) if outdir: @@ -345,13 +347,14 @@ def arg_parser(): # type: () -> argparse.ArgumentParser pkg = pkg_resources.require("cwltest") if pkg: - ver = u"%s %s" % (sys.argv[0], pkg[0].version) + ver = f"{sys.argv[0]} {pkg[0].version}" else: - ver = u"%s %s" % (sys.argv[0], "unknown version") + ver = "{} {}".format(sys.argv[0], "unknown version") parser.add_argument("--version", action="https://github.com/version", version=ver) return parser + def expand_number_range(nr: str) -> List[int]: ans: List[int] = [] for s in nr.split(","): @@ -362,6 +365,7 @@ def expand_number_range(nr: str) -> List[int]: ans.append(int(s) - 1) return ans + def main(): # type: () -> int args = arg_parser().parse_args(sys.argv[1:]) @@ -558,12 +562,12 @@ def main(): # type: () -> int else: color = "yellow" - with open("{}/{}.json".format(args.badgedir, t), "w") as out: + with open(f"{args.badgedir}/{t}.json", "w") as out: out.write( json.dumps( { - "subject": "{}".format(t), - "status": "{}%".format(percent), + "subject": f"{t}", + "status": f"{percent}%", "color": color, } ) diff --git a/cwltest/tests/test_categories.py b/cwltest/tests/test_categories.py index 71798e9..d1e1de2 100644 --- a/cwltest/tests/test_categories.py +++ b/cwltest/tests/test_categories.py @@ -8,11 +8,17 @@ import defusedxml.ElementTree as ET import schema_salad.ref_resolver + class TestCategories(unittest.TestCase): maxDiff = None def test_unsupported_with_required_tests(self): - args = ["--test", schema_salad.ref_resolver.file_uri(get_data("tests/test-data/required-unsupported.yml"))] + args = [ + "--test", + schema_salad.ref_resolver.file_uri( + get_data("tests/test-data/required-unsupported.yml") + ), + ] try: cwd = os.getcwd() os.chdir(get_data("tests/test-data/")) @@ -47,7 +53,12 @@ def test_unsupported_with_required_tests(self): ) def test_unsupported_with_optional_tests(self): - args = ["--test", schema_salad.ref_resolver.file_uri(get_data("tests/test-data/optional-unsupported.yml"))] + args = [ + "--test", + schema_salad.ref_resolver.file_uri( + get_data("tests/test-data/optional-unsupported.yml") + ), + ] error_code, stdout, stderr = run_with_mock_cwl_runner(args) self.assertEqual(error_code, 0) self.assertEqual( @@ -58,7 +69,12 @@ def test_unsupported_with_optional_tests(self): ) def test_error_with_optional_tests(self): - args = ["--test", schema_salad.ref_resolver.file_uri(get_data("tests/test-data/optional-error.yml"))] + args = [ + "--test", + schema_salad.ref_resolver.file_uri( + get_data("tests/test-data/optional-error.yml") + ), + ] error_code, stdout, stderr = run_with_mock_cwl_runner(args) self.assertEqual(error_code, 1) self.assertIn("1 failures", stderr) @@ -67,7 +83,9 @@ def test_category_in_junit_xml(self): junit_xml_report = get_data("tests/test-data/junit-report.xml") args = [ "--test", - schema_salad.ref_resolver.file_uri(get_data("tests/test-data/optional-error.yml")), + schema_salad.ref_resolver.file_uri( + get_data("tests/test-data/optional-error.yml") + ), "--junit-xml", junit_xml_report, ] diff --git a/cwltest/tests/test_prepare.py b/cwltest/tests/test_prepare.py index 3d93487..d09f039 100644 --- a/cwltest/tests/test_prepare.py +++ b/cwltest/tests/test_prepare.py @@ -4,10 +4,10 @@ class TestPrepareCommand(unittest.TestCase): - """ Test prepare_test_command() """ + """Test prepare_test_command()""" def test_unix_relative_path(self): - """ Confirm unix style to windows style path corrections. """ + """Confirm unix style to windows style path corrections.""" command = prepare_test_command( tool="cwl-runner", args=[], @@ -19,7 +19,7 @@ def test_unix_relative_path(self): "job": "v1.0/bwa-mem-job.json", "tags": ["required"], }, - cwd=os.getcwd() + cwd=os.getcwd(), ) if os.name == "nt": self.assertEqual(command[3], "v1.0\\bwa-mem-tool.cwl") diff --git a/cwltest/utils.py b/cwltest/utils.py index 034b538..13ea3fb 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -7,7 +7,7 @@ REQUIRED = "required" -class TestResult(object): +class TestResult: """Encapsulate relevant test result data.""" @@ -30,12 +30,12 @@ def __init__( def create_test_case(self, test): # type: (Dict[Text, Any]) -> junit_xml.TestCase - doc = test.get(u"doc", "N/A").strip() + doc = test.get("doc", "N/A").strip() if test.get("tags"): category = ", ".join(test["tags"]) else: category = REQUIRED - short_name = test.get(u"short_name") + short_name = test.get("short_name") case = junit_xml.TestCase( doc, elapsed_sec=self.duration, @@ -53,12 +53,12 @@ class CompareFail(Exception): @classmethod def format(cls, expected, actual, cause=None): # type: (Any, Any, Any) -> CompareFail - message = u"expected: %s\ngot: %s" % ( + message = "expected: {}\ngot: {}".format( json.dumps(expected, indent=4, sort_keys=True), json.dumps(actual, indent=4, sort_keys=True), ) if cause: - message += u"\ncaused by: %s" % cause + message += "\ncaused by: %s" % cause return cls(message) @@ -84,7 +84,7 @@ def compare_location(expected, actual): raise CompareFail.format( expected, actual, - u"%s does not end with %s" % (actual[comp], expected[comp]), + f"{actual[comp]} does not end with {expected[comp]}", ) @@ -98,7 +98,7 @@ def compare_contents(expected, actual): expected, actual, json.dumps( - u"Output file contents do not match: actual '%s' is not equal to expected '%s'" + "Output file contents do not match: actual '%s' is not equal to expected '%s'" % (actual_contents, expected_contents) ), ) @@ -111,7 +111,7 @@ def check_keys(keys, expected, actual): compare(expected.get(k), actual.get(k)) except CompareFail as e: raise CompareFail.format( - expected, actual, u"field '%s' failed comparison: %s" % (k, str(e)) + expected, actual, f"field '{k}' failed comparison: {str(e)}" ) @@ -128,11 +128,11 @@ def compare_directory(expected, actual): # type: (Dict[str,Any], Dict[str,Any]) -> None if actual.get("class") != "Directory": raise CompareFail.format( - expected, actual, u"expected object with a class 'Directory'" + expected, actual, "expected object with a class 'Directory'" ) if "listing" not in actual: raise CompareFail.format( - expected, actual, u"'listing' is mandatory field in Directory object" + expected, actual, "'listing' is mandatory field in Directory object" ) for i in expected["listing"]: found = False @@ -147,7 +147,7 @@ def compare_directory(expected, actual): raise CompareFail.format( expected, actual, - u"%s not found" % json.dumps(i, indent=4, sort_keys=True), + "%s not found" % json.dumps(i, indent=4, sort_keys=True), ) compare_file(expected, actual) @@ -159,12 +159,12 @@ def compare_dict(expected, actual): compare(expected[c], actual.get(c)) except CompareFail as e: raise CompareFail.format( - expected, actual, u"failed comparison for key '%s': %s" % (c, e) + expected, actual, f"failed comparison for key '{c}': {e}" ) extra_keys = set(actual.keys()).difference(list(expected.keys())) for k in extra_keys: if actual[k] is not None: - raise CompareFail.format(expected, actual, u"unexpected key '%s'" % k) + raise CompareFail.format(expected, actual, "unexpected key '%s'" % k) def compare(expected, actual): # type: (Any, Any) -> None @@ -190,7 +190,7 @@ def compare(expected, actual): # type: (Any, Any) -> None raise CompareFail.format(expected, actual) if len(expected) != len(actual): - raise CompareFail.format(expected, actual, u"lengths don't match") + raise CompareFail.format(expected, actual, "lengths don't match") for c in range(0, len(expected)): try: compare(expected[c], actual[c]) From 6c38dbe195022babfeb78acc6e5f643392b23bd8 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Wed, 1 Sep 2021 16:01:24 +0200 Subject: [PATCH 012/165] sort inputs --- cwltest/__init__.py | 26 ++++++++++++-------------- cwltest/utils.py | 3 +-- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/cwltest/__init__.py b/cwltest/__init__.py index dcf9df7..d2d40aa 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -5,28 +5,29 @@ import logging import os import shutil +import subprocess # nosec import sys import tempfile import threading import time -from typing import Any, Dict, List, Optional, Set, Text, Union -from concurrent.futures import ThreadPoolExecutor from collections import defaultdict -from rdflib import Graph +from concurrent.futures import ThreadPoolExecutor +from shlex import quote +from typing import Any, Dict, List, Optional, Set, Union -import ruamel.yaml as yaml +import junit_xml +import pkg_resources # part of setuptools import ruamel.yaml.scanner as yamlscanner +import schema_salad.avro.schema import schema_salad.ref_resolver import schema_salad.schema -import schema_salad.avro.schema -import pkg_resources # part of setuptools +from rdflib import Graph -import junit_xml from cwltest.utils import ( - compare, + REQUIRED, CompareFail, TestResult, - REQUIRED, + compare, get_test_number_by_key, ) @@ -37,9 +38,6 @@ UNSUPPORTED_FEATURE = 33 DEFAULT_TIMEOUT = 600 # 10 minutes -import subprocess # nosec -from shlex import quote - templock = threading.Lock() @@ -391,8 +389,8 @@ def main(): # type: () -> int ( document_loader, avsc_names, - schema_metadata, - metaschema_loader, + _, + _, ) = schema_salad.schema.load_schema( "https://w3id.org/cwl/cwltest/cwltest-schema.yml", cache=cache ) diff --git a/cwltest/utils.py b/cwltest/utils.py index 13ea3fb..984d8a8 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -1,6 +1,5 @@ import json - -from typing import Any, Dict, Set, Text, List, Optional +from typing import Any, Dict, List, Optional, Set, Text import junit_xml From 097088ecfd599c7a096e9d3fc05d458456d2a641 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Wed, 1 Sep 2021 16:18:17 +0200 Subject: [PATCH 013/165] print command in verbose mode --- cwltest/__init__.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/cwltest/__init__.py b/cwltest/__init__.py index d2d40aa..577a19f 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -96,6 +96,7 @@ def run_test( test_number, # type: int total_tests, # type: int timeout, # type: int + junit_verbose=False, # type: bool verbose=False, # type: bool ): # type: (...) -> TestResult @@ -115,7 +116,7 @@ def run_test( process = None # type: Optional[subprocess.Popen[str]] cwd = os.getcwd() test_command = prepare_test_command( - args.tool, args.args, args.testargs, test, cwd, verbose + args.tool, args.args, args.testargs, test, cwd, junit_verbose ) if test.get("short_name"): @@ -135,6 +136,8 @@ def run_test( "%sTest [%i/%i] %s%s\n" % (prefix, test_number, total_tests, test.get("doc"), suffix) ) + if verbose: + sys.stderr.write(f"Running: {' '.join(test_command)}\n") sys.stderr.flush() start_time = time.time() @@ -386,12 +389,7 @@ def main(): # type: () -> int "utf-8" ) } # type: Optional[Dict[str, Union[str, Graph, bool]]] - ( - document_loader, - avsc_names, - _, - _, - ) = schema_salad.schema.load_schema( + (document_loader, avsc_names, _, _,) = schema_salad.schema.load_schema( "https://w3id.org/cwl/cwltest/cwltest-schema.yml", cache=cache ) @@ -500,6 +498,7 @@ def main(): # type: () -> int len(tests), args.timeout, args.junit_verbose, + args.verbose, ) for i in ntest ] From e27d9bed1e48ad54727ac24874339d6f2b36304e Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Tue, 5 Oct 2021 17:55:57 +0200 Subject: [PATCH 014/165] update badges --- README.rst | 49 ++++++++++++++++++++++++++++++++++++++----------- appveyor.yml | 48 ------------------------------------------------ 2 files changed, 38 insertions(+), 59 deletions(-) delete mode 100644 appveyor.yml diff --git a/README.rst b/README.rst index decd324..bd0df40 100644 --- a/README.rst +++ b/README.rst @@ -1,30 +1,57 @@ -|Linux Build Status| |Windows Build status| |Code coverage| +========================================== +Common Workflow Language testing framework +========================================== + +|Linux Build Status| |Code coverage| + +PyPI: |PyPI Version| |PyPI Downloads Month| |Total PyPI Downloads| -.. |Linux Build Status| image:: https://img.shields.io/travis/common-workflow-language/cwltest/master.svg?label=unix%20build - :target: https://travis-ci.org/common-workflow-language/cwltest -.. |Windows Build status| image:: https://img.shields.io/appveyor/ci/mr-c/cwltest/master.svg?label=windows%20build - :target: https://ci.appveyor.com/project/mr-c/cwltest/branch/master +Conda: |Conda Version| |Conda Installs| + +.. |Linux Build Status| image:: https://github.com/common-workflow-language/cwltest/actions/workflows/ci-tests.yml/badge.svg?branch=main + :target: https://github.com/common-workflow-language/cwltest/actions/workflows/ci-tests.yml .. |Code coverage| image:: https://codecov.io/gh/common-workflow-language/cwltest/branch/master/graph/badge.svg :target: https://codecov.io/gh/common-workflow-language/cwltest -========================================== -Common workflow language testing framework -========================================== +.. |PyPI Version| image:: https://badge.fury.io/py/cwltest.svg + :target: https://badge.fury.io/py/cwltest + +.. |PyPI Downloads Month| image:: https://pepy.tech/badge/cwltest/month + :target: https://pepy.tech/project/cwltest + +.. |Total PyPI Downloads| image:: https://static.pepy.tech/personalized-badge/cwltest?period=total&units=international_system&left_color=black&right_color=orange&left_text=Total%20PyPI%20Downloads + :target: https://pepy.tech/project/cwltest + +.. |Conda Version| image:: https://anaconda.org/bioconda/cwltest/badges/version.svg + :target: https://anaconda.org/bioconda/cwltest + +.. |Conda Installs| image:: https://anaconda.org/bioconda/cwltest/badges/downloads.svg + :target: https://anaconda.org/bioconda/cwltest This is a testing tool for checking the output of Tools and Workflows described with the Common Workflow Language. Among other uses, it is used to run the CWL conformance tests. -This is written and tested for Python 2.7, 3.4, 3.5, 3.6, and 3.7 +This is written and tested for Python 3.6, 3.7, 3.8, and 3.9 Install ------- -Installing the official package from PyPi:: +Installing the official package from PyPi + +.. code:: bash pip install cwltest -Or from source:: +Or from bioconda + +.. code:: bash + + conda install -c bioconda cwltest + +Or from source + +.. code:: bash git clone https://github.com/common-workflow-language/cwltest.git cd cwltest && python setup.py install diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 8ca6123..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,48 +0,0 @@ -version: .{build}-{branch} - -cache: - - '%LOCALAPPDATA%\pip\Cache' - -environment: - - SYSTEMROOT: "C:\\WINDOWS" - - matrix: - - PYTHON: "C:\\Python35-x64" - PYTHON_VERSION: "3.5.x" - PYTHON_ARCH: "64" - - - PYTHON: "C:\\Python36-x64" - PYTHON_VERSION: "3.6.x" - PYTHON_ARCH: "64" - - - PYTHON: "C:\\Python37-x64" - PYTHON_VERSION: "3.7.x" - PYTHON_ARCH: "64" - - - PYTHON: "C:\\Python38-x64" - PYTHON_VERSION: "3.8.x" - PYTHON_ARCH: "64" - -install: - - "%PYTHON%\\python.exe -m pip install -U pip setuptools^>=20.3" - - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" - # Note the use of a `^` to escape the `>` - -build_script: - - | - %PYTHON%\\python.exe -m pip install -U wheel pytest pytest-xdist - %PYTHON%\\python.exe -m pip install -e . - -test_script: - - | - %PYTHON%\\python.exe setup.py test --addopts "--verbose -p no:cacheprovider --junit-xml=tests.xml" - -on_finish: - - ps: | - $wc = New-Object 'System.Net.WebClient' - $wc.UploadFile("https://ci.appveyor.com/api/testresults/junit/$($Env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests.xml)) - -branches: - only: - - master From f69e1249cc44e916ba2c2df3886c52691275ebb7 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Mon, 15 Nov 2021 10:39:39 -0500 Subject: [PATCH 015/165] Collect output from timed-out tests This should fix https://github.com/common-workflow-language/cwltest/issues/121 --- cwltest/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cwltest/__init__.py b/cwltest/__init__.py index 577a19f..3dc97c8 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -204,6 +204,10 @@ def run_test( " ".join([quote(tc) for tc in test_command]), ) _logger.error(test.get("doc")) + # Kill and re-communicate to get the logs and reap the child, as + # instructed in the subprocess docs. + process.kill() + outstr, outerr = process.communicate() return TestResult(2, outstr, outerr, timeout, args.classname, "Test timed out") finally: if process is not None and process.returncode is None: From af69301f47f8a15520e228d9a8c05ae9e0176fa0 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Mon, 15 Nov 2021 18:02:57 +0100 Subject: [PATCH 016/165] only if we got a Process object back --- cwltest/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cwltest/__init__.py b/cwltest/__init__.py index 3dc97c8..9e0ec7a 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -206,8 +206,9 @@ def run_test( _logger.error(test.get("doc")) # Kill and re-communicate to get the logs and reap the child, as # instructed in the subprocess docs. - process.kill() - outstr, outerr = process.communicate() + if process: + process.kill() + outstr, outerr = process.communicate() return TestResult(2, outstr, outerr, timeout, args.classname, "Test timed out") finally: if process is not None and process.returncode is None: From 027e688bb2f0292c497c24d0e50abb1396e14827 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Mon, 15 Nov 2021 18:29:02 +0100 Subject: [PATCH 017/165] modernize tests --- cwltest/tests/test_argparse.py | 27 ++--- cwltest/tests/test_categories.py | 159 +++++++++++++++--------------- cwltest/tests/test_compare.py | 107 ++++++++++---------- cwltest/tests/test_prepare.py | 47 +++++---- cwltest/tests/test_short_names.py | 94 +++++++++--------- 5 files changed, 207 insertions(+), 227 deletions(-) diff --git a/cwltest/tests/test_argparse.py b/cwltest/tests/test_argparse.py index 6a5c067..729cd5c 100644 --- a/cwltest/tests/test_argparse.py +++ b/cwltest/tests/test_argparse.py @@ -1,20 +1,13 @@ -import unittest from cwltest import arg_parser -class TestArgparse(unittest.TestCase): - def setUp(self): - self.parser = arg_parser() - - def test_arg(self): - parsed = self.parser.parse_args( - ["--test", "test_name", "-n", "52", "--tool", "cwltool", "-j", "4"] - ) - self.assertEqual(parsed.test, "test_name") - self.assertEqual(parsed.n, "52") - self.assertEqual(parsed.tool, "cwltool") - self.assertEqual(parsed.j, 4) - - -if __name__ == "__main__": - unittest.main() +def test_arg(): + """Basic test of the argparse.""" + parser = arg_parser() + parsed = parser.parse_args( + ["--test", "test_name", "-n", "52", "--tool", "cwltool", "-j", "4"] + ) + assert parsed.test == "test_name" + assert parsed.n == "52" + assert parsed.tool == "cwltool" + assert parsed.j == 4 diff --git a/cwltest/tests/test_categories.py b/cwltest/tests/test_categories.py index d1e1de2..77e8711 100644 --- a/cwltest/tests/test_categories.py +++ b/cwltest/tests/test_categories.py @@ -1,97 +1,92 @@ -import unittest import re import os from os import linesep as n from os import sep as p +from pathlib import Path from .util import run_with_mock_cwl_runner, get_data import defusedxml.ElementTree as ET import schema_salad.ref_resolver -class TestCategories(unittest.TestCase): - maxDiff = None +def test_unsupported_with_required_tests(): + args = [ + "--test", + schema_salad.ref_resolver.file_uri( + get_data("tests/test-data/required-unsupported.yml") + ), + ] + try: + cwd = os.getcwd() + os.chdir(get_data("tests/test-data/")) + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + finally: + os.chdir(cwd) - def test_unsupported_with_required_tests(self): - args = [ - "--test", - schema_salad.ref_resolver.file_uri( - get_data("tests/test-data/required-unsupported.yml") - ), - ] - try: - cwd = os.getcwd() - os.chdir(get_data("tests/test-data/")) - error_code, stdout, stderr = run_with_mock_cwl_runner(args) - finally: - os.chdir(cwd) + assert error_code == 1 + print(stderr) + stderr = re.sub(r" '?--outdir=[^ ]*", "", stderr) + if os.name == "nt": + q = "'" + else: + q = "" + assert ( + "Test [1/2] Required test that is unsupported (without tags){n}" + "{n}" + "Test 1 failed: mock-cwl-runner --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" + "Required test that is unsupported (without tags){n}" + "Does not support required feature{n}" + "{n}" + "Test [2/2] Required test that is unsupported (with tags){n}" + "{n}" + "Test 2 failed: mock-cwl-runner --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" + "Required test that is unsupported (with tags){n}" + "Does not support required feature{n}" + "{n}" + "0 tests passed, 2 failures, 0 unsupported features{n}".format(n=n, p=p, q=q) + ) == stderr - self.assertEqual(error_code, 1) - print(stderr) - stderr = re.sub(r" '?--outdir=[^ ]*", "", stderr) - if os.name == "nt": - q = "'" - else: - q = "" - self.assertEqual( - "Test [1/2] Required test that is unsupported (without tags){n}" - "{n}" - "Test 1 failed: mock-cwl-runner --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" - "Required test that is unsupported (without tags){n}" - "Does not support required feature{n}" - "{n}" - "Test [2/2] Required test that is unsupported (with tags){n}" - "{n}" - "Test 2 failed: mock-cwl-runner --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" - "Required test that is unsupported (with tags){n}" - "Does not support required feature{n}" - "{n}" - "0 tests passed, 2 failures, 0 unsupported features{n}".format( - n=n, p=p, q=q - ), - stderr, - ) - def test_unsupported_with_optional_tests(self): - args = [ - "--test", - schema_salad.ref_resolver.file_uri( - get_data("tests/test-data/optional-unsupported.yml") - ), - ] - error_code, stdout, stderr = run_with_mock_cwl_runner(args) - self.assertEqual(error_code, 0) - self.assertEqual( - "Test [1/1] Optional test that is unsupported{n}{n}" - "0 tests passed, 1 unsupported " - "features{n}".format(n=n), - stderr, - ) +def test_unsupported_with_optional_tests(): + args = [ + "--test", + schema_salad.ref_resolver.file_uri( + get_data("tests/test-data/optional-unsupported.yml") + ), + ] + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + assert error_code == 0 + assert ( + "Test [1/1] Optional test that is unsupported{n}{n}" + "0 tests passed, 1 unsupported " + "features{n}".format(n=n) + ) == stderr + + +def test_error_with_optional_tests(): + args = [ + "--test", + schema_salad.ref_resolver.file_uri( + get_data("tests/test-data/optional-error.yml") + ), + ] + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + assert error_code == 1 + assert "1 failures" in stderr - def test_error_with_optional_tests(self): - args = [ - "--test", - schema_salad.ref_resolver.file_uri( - get_data("tests/test-data/optional-error.yml") - ), - ] - error_code, stdout, stderr = run_with_mock_cwl_runner(args) - self.assertEqual(error_code, 1) - self.assertIn("1 failures", stderr) - def test_category_in_junit_xml(self): - junit_xml_report = get_data("tests/test-data/junit-report.xml") - args = [ - "--test", - schema_salad.ref_resolver.file_uri( - get_data("tests/test-data/optional-error.yml") - ), - "--junit-xml", - junit_xml_report, - ] - run_with_mock_cwl_runner(args) - tree = ET.parse(junit_xml_report) - root = tree.getroot() - category = root.find("testsuite").find("testcase").attrib["class"] - self.assertEqual(category, "js, init_work_dir") - os.remove(junit_xml_report) +def test_category_in_junit_xml(tmp_path: Path): + junit_xml_report = tmp_path / "junit-report.xml" + args = [ + "--test", + schema_salad.ref_resolver.file_uri( + get_data("tests/test-data/optional-error.yml") + ), + "--junit-xml", + str(junit_xml_report), + ] + run_with_mock_cwl_runner(args) + tree = ET.parse(junit_xml_report) + root = tree.getroot() + category = root.find("testsuite").find("testcase").attrib["class"] + assert category == "js, init_work_dir" diff --git a/cwltest/tests/test_compare.py b/cwltest/tests/test_compare.py index 5a20cae..15003ed 100644 --- a/cwltest/tests/test_compare.py +++ b/cwltest/tests/test_compare.py @@ -1,64 +1,63 @@ -import unittest from .util import get_data from cwltest import CompareFail from cwltest.utils import compare_file, compare +import pytest -class TestCompareFile(unittest.TestCase): - def test_compare_file(self): - expected = { - "location": "cores.txt", - "size": 2, - "class": "File", - "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", - } - actual = { - "basename": "cores.txt", - "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", - "class": "File", - "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", - "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", - "size": 2, - } - try: - compare_file(expected, actual) - except CompareFail: - self.fail("File comparison failed unexpectedly") +def test_compare_file(): + expected = { + "location": "cores.txt", + "size": 2, + "class": "File", + "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", + } - def test_compare_contents_success(self): - expected = { - "location": "cores.txt", - "size": 2, - "class": "File", - "contents": "2\n", - } + actual = { + "basename": "cores.txt", + "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", + "class": "File", + "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", + "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", + "size": 2, + } + compare_file(expected, actual) - actual = { - "basename": "cores.txt", - "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", - "class": "File", - "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", - "path": get_data("tests/test-data/cores.txt"), - "size": 2, - } - compare(expected, actual) - def test_compare_contents_failure(self): - expected = { - "location": "cores.txt", - "size": 2, - "class": "File", - "contents": "2", - } +def test_compare_contents_success(): + expected = { + "location": "cores.txt", + "size": 2, + "class": "File", + "contents": "2\n", + } - actual = { - "basename": "cores.txt", - "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", - "class": "File", - "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", - "path": get_data("tests/test-data/cores.txt"), - "size": 2, - } - with self.assertRaises(CompareFail): - compare_file(expected, actual) + actual = { + "basename": "cores.txt", + "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", + "class": "File", + "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", + "path": get_data("tests/test-data/cores.txt"), + "size": 2, + } + compare(expected, actual) + + +def test_compare_contents_failure(): + expected = { + "location": "cores.txt", + "size": 2, + "class": "File", + "contents": "2", + } + + actual = { + "basename": "cores.txt", + "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", + "class": "File", + "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", + "path": get_data("tests/test-data/cores.txt"), + "size": 2, + } + with pytest.raises(CompareFail): + compare_file(expected, actual) diff --git a/cwltest/tests/test_prepare.py b/cwltest/tests/test_prepare.py index d09f039..3c2ff6f 100644 --- a/cwltest/tests/test_prepare.py +++ b/cwltest/tests/test_prepare.py @@ -1,29 +1,26 @@ +"""Test prepare_test_command()""" import os -import unittest from cwltest import prepare_test_command -class TestPrepareCommand(unittest.TestCase): - """Test prepare_test_command()""" - - def test_unix_relative_path(self): - """Confirm unix style to windows style path corrections.""" - command = prepare_test_command( - tool="cwl-runner", - args=[], - testargs=None, - test={ - "doc": "General test of command line generation", - "output": {"args": ["echo"]}, - "tool": "v1.0/bwa-mem-tool.cwl", - "job": "v1.0/bwa-mem-job.json", - "tags": ["required"], - }, - cwd=os.getcwd(), - ) - if os.name == "nt": - self.assertEqual(command[3], "v1.0\\bwa-mem-tool.cwl") - self.assertEqual(command[4], "v1.0\\bwa-mem-job.json") - else: - self.assertEqual(command[3], "v1.0/bwa-mem-tool.cwl") - self.assertEqual(command[4], "v1.0/bwa-mem-job.json") +def test_unix_relative_path(): + """Confirm unix style to windows style path corrections.""" + command = prepare_test_command( + tool="cwl-runner", + args=[], + testargs=None, + test={ + "doc": "General test of command line generation", + "output": {"args": ["echo"]}, + "tool": "v1.0/bwa-mem-tool.cwl", + "job": "v1.0/bwa-mem-job.json", + "tags": ["required"], + }, + cwd=os.getcwd(), + ) + if os.name == "nt": + assert command[3] == "v1.0\\bwa-mem-tool.cwl" + assert command[4] == "v1.0\\bwa-mem-job.json" + else: + assert command[3] == "v1.0/bwa-mem-tool.cwl" + assert command[4] == "v1.0/bwa-mem-job.json" diff --git a/cwltest/tests/test_short_names.py b/cwltest/tests/test_short_names.py index 6efda7f..84a594c 100644 --- a/cwltest/tests/test_short_names.py +++ b/cwltest/tests/test_short_names.py @@ -1,56 +1,52 @@ -import unittest - import os from os import linesep as n +from pathlib import Path from .util import run_with_mock_cwl_runner, get_data import defusedxml.ElementTree as ET -class TestShortNames(unittest.TestCase): - def test_stderr_output(self): - args = ["--test", get_data("tests/test-data/short-names.yml")] - error_code, stdout, stderr = run_with_mock_cwl_runner(args) - self.assertIn( - "Test [1/1] opt-error: Test with a short name{n}".format(n=n), stderr - ) - - def test_run_by_short_name(self): - short_name = "opt-error" - args = [ - "--test", - get_data("tests/test-data/with-and-without-short-names.yml"), - "-s", - short_name, - ] - error_code, stdout, stderr = run_with_mock_cwl_runner(args) - self.assertIn("Test [2/2] opt-error: Test with a short name", stderr) - self.assertNotIn("Test [1/2]", stderr) - - def test_list_tests(self): - args = [ - "--test", - get_data("tests/test-data/with-and-without-short-names.yml"), - "-l", - ] - error_code, stdout, stderr = run_with_mock_cwl_runner(args) - self.assertEqual( - "[1] Test without a short name{n}" - "[2] opt-error: Test with a short name{n}".format(n=n), - stdout, - ) - - def test_short_name_in_junit_xml(self): - junit_xml_report = get_data("tests/test-data/junit-report.xml") - args = [ - "--test", - get_data("tests/test-data/short-names.yml"), - "--junit-xml", - junit_xml_report, - ] - run_with_mock_cwl_runner(args) - tree = ET.parse(junit_xml_report) - root = tree.getroot() - category = root.find("testsuite").find("testcase").attrib["file"] - self.assertEqual(category, "opt-error") - os.remove(junit_xml_report) +def test_stderr_output(): + args = ["--test", get_data("tests/test-data/short-names.yml")] + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + assert f"Test [1/1] opt-error: Test with a short name{n}" in stderr + + +def test_run_by_short_name(): + short_name = "opt-error" + args = [ + "--test", + get_data("tests/test-data/with-and-without-short-names.yml"), + "-s", + short_name, + ] + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + assert "Test [2/2] opt-error: Test with a short name" in stderr + assert "Test [1/2]" not in stderr + + +def test_list_tests(): + args = [ + "--test", + get_data("tests/test-data/with-and-without-short-names.yml"), + "-l", + ] + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + assert ( + f"[1] Test without a short name{n}" f"[2] opt-error: Test with a short name{n}" + ) in stdout + + +def test_short_name_in_junit_xml(tmp_path: Path): + junit_xml_report = tmp_path / "junit-report.xml" + args = [ + "--test", + get_data("tests/test-data/short-names.yml"), + "--junit-xml", + str(junit_xml_report), + ] + run_with_mock_cwl_runner(args) + tree = ET.parse(junit_xml_report) + root = tree.getroot() + category = root.find("testsuite").find("testcase").attrib["file"] + assert category == "opt-error" From 202b77a56ceb192a060f651ec2e4a826c25be217 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Mon, 15 Nov 2021 19:23:56 +0100 Subject: [PATCH 018/165] test timeout feature --- .coveragerc | 14 +++++++++ Makefile | 2 +- cwltest/tests/mock_cwl_runner.py | 10 +++++- cwltest/tests/test-data/timeout.cwl | 5 +++ cwltest/tests/test-data/timeout.yml | 9 ++++++ cwltest/tests/test-data/v1.0/empty.json | 1 + cwltest/tests/test_timeout.py | 42 +++++++++++++++++++++++++ cwltest/tests/util.py | 7 ++--- test-requirements.txt | 1 - tox.ini | 2 +- 10 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 .coveragerc create mode 100644 cwltest/tests/test-data/timeout.cwl create mode 100644 cwltest/tests/test-data/timeout.yml create mode 100644 cwltest/tests/test-data/v1.0/empty.json create mode 100644 cwltest/tests/test_timeout.py diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..4a89de0 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,14 @@ +[run] +branch = True +source = cwltest +omit = cwltest/tests/* + +[report] +exclude_lines = + if self.debug: + pragma: no cover + raise NotImplementedError + if __name__ == .__main__.: +ignore_errors = True +omit = + cwltest/tests/* diff --git a/Makefile b/Makefile index e67f0e1..abda48e 100644 --- a/Makefile +++ b/Makefile @@ -112,7 +112,7 @@ diff_pylint_report: pylint_report.txt diff-quality --violations=pylint pylint_report.txt .coverage: $(PYSOURCES) all - python setup.py test --addopts "--cov --cov-config=.coveragerc --cov-report= -n auto ${PYTEST_EXTRA}" + python setup.py test --addopts "--cov --cov-config=.coveragerc --cov-report= ${PYTEST_EXTRA}" coverage.xml: .coverage coverage xml diff --git a/cwltest/tests/mock_cwl_runner.py b/cwltest/tests/mock_cwl_runner.py index a352f7d..478e504 100644 --- a/cwltest/tests/mock_cwl_runner.py +++ b/cwltest/tests/mock_cwl_runner.py @@ -1,12 +1,15 @@ import argparse +import sys +from time import sleep from cwltest import UNSUPPORTED_FEATURE UNSUPPORTED_FEATURE_TOOL = "return-unsupported.cwl" ERROR_TOOL = "return-1.cwl" +TIMEOUT_TOOL = "timeout.cwl" -def main(): # type: ()->int +def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("processfile") parser.add_argument("jobfile") @@ -20,6 +23,11 @@ def main(): # type: ()->int exit(UNSUPPORTED_FEATURE) elif args.processfile.endswith(ERROR_TOOL): exit(1) + elif args.processfile.endswith(TIMEOUT_TOOL): + print("timeout stderr", file=sys.stderr) + sys.stderr.flush() + sleep(100000) + exit(1) exit(0) diff --git a/cwltest/tests/test-data/timeout.cwl b/cwltest/tests/test-data/timeout.cwl new file mode 100644 index 0000000..a487298 --- /dev/null +++ b/cwltest/tests/test-data/timeout.cwl @@ -0,0 +1,5 @@ +class: CommandLineTool +cwlVersion: v1.0 +inputs: [] +outputs: [] +baseCommand: [sleep, "15"] diff --git a/cwltest/tests/test-data/timeout.yml b/cwltest/tests/test-data/timeout.yml new file mode 100644 index 0000000..30231d6 --- /dev/null +++ b/cwltest/tests/test-data/timeout.yml @@ -0,0 +1,9 @@ +- job: v1.0/empty.json + output: + output_txt: + class: File + checksum: sha1$47a013e660d408619d894b20806b1d5086aab03b + location: output.txt + size: 13 + tool: timeout.cwl + doc: Test of timeout stdout and stderr capture diff --git a/cwltest/tests/test-data/v1.0/empty.json b/cwltest/tests/test-data/v1.0/empty.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/cwltest/tests/test-data/v1.0/empty.json @@ -0,0 +1 @@ +{} diff --git a/cwltest/tests/test_timeout.py b/cwltest/tests/test_timeout.py new file mode 100644 index 0000000..431e665 --- /dev/null +++ b/cwltest/tests/test_timeout.py @@ -0,0 +1,42 @@ +import re +import os +from os import linesep as n +from os import sep as p +from pathlib import Path + +import defusedxml.ElementTree as ET + +from .util import run_with_mock_cwl_runner, get_data +import schema_salad.ref_resolver + + +def test_timeout_stderr_stdout(tmp_path): + junit_xml_report = tmp_path / "junit-report.xml" + + args = [ + "--test", + schema_salad.ref_resolver.file_uri(get_data("tests/test-data/timeout.yml")), + "--timeout", + "5", + "--junit-xml", + str(junit_xml_report), + ] + try: + cwd = os.getcwd() + os.chdir(get_data("tests/test-data/")) + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + finally: + os.chdir(cwd) + + assert error_code == 1 + assert "Test 1 timed out" in stderr + tree = ET.parse(junit_xml_report) + try: + root = tree.getroot() + timeout_text = root.find("testsuite").find("testcase").find("failure").text + timeout_stderr = root.find("testsuite").find("testcase").find("system-err").text + assert "Test timed out" in timeout_text + assert "timeout stderr" in timeout_stderr + except AttributeError as e: + print(junit_xml_report.read_text()) + raise e diff --git a/cwltest/tests/util.py b/cwltest/tests/util.py index 414db00..25879bc 100644 --- a/cwltest/tests/util.py +++ b/cwltest/tests/util.py @@ -1,5 +1,4 @@ import os -import sys import subprocess # nosec @@ -11,9 +10,9 @@ def get_data(filename): - filename = os.path.normpath( - filename - ) # normalizing path depending on OS or else it will cause problem when joining path + filename = os.path.normpath(filename) + # normalizing path depending on OS or else it will cause problem when + # joining path filepath = None try: filepath = resource_filename(Requirement.parse("cwltest"), filename) diff --git a/test-requirements.txt b/test-requirements.txt index fb43315..eb7dc7f 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,3 +1,2 @@ pytest >= 6.2, < 6.3 pytest-cov -pytest-xdist diff --git a/tox.ini b/tox.ini index c0f3f1a..52e21a3 100644 --- a/tox.ini +++ b/tox.ini @@ -12,7 +12,7 @@ skipsdist = True skip_missing_interpreters = True [pytest] -addopts=-n auto --pyargs cwltest +addopts = --pyargs cwltest testpaths = cwltest/tests [gh-actions] From 8958ba01f77b4b64c94cc9a3fa8ea89d77183ab3 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Mon, 15 Nov 2021 19:44:51 +0100 Subject: [PATCH 019/165] support Python 3.10 --- .flake8 | 4 ++ .github/workflows/ci-tests.yml | 16 +++-- MANIFEST.in | 2 +- Makefile | 2 +- cwltest/utils.py | 8 +-- ..._requirements.txt => mypy-requirements.txt | 0 release-test.sh | 16 +++-- setup.py | 1 + tox.ini | 64 +++++++++++-------- 9 files changed, 66 insertions(+), 47 deletions(-) create mode 100644 .flake8 rename mypy_requirements.txt => mypy-requirements.txt (100%) diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..35967ff --- /dev/null +++ b/.flake8 @@ -0,0 +1,4 @@ +[flake8] +ignore = E203, E266, E501, W503, E211, E731 +max-line-length = 88 +select = B,C,E,F,W,T4,B9 diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index cf34d1d..573fb61 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -6,6 +6,10 @@ on: pull_request: branches: [ main ] +concurrency: + group: build-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: tox: @@ -16,7 +20,7 @@ jobs: strategy: matrix: py-ver-major: [3] - py-ver-minor: [6, 7, 8, 9] + py-ver-minor: [6, 7, 8, 9, 10] step: [lint, unit, mypy] env: @@ -54,7 +58,7 @@ jobs: - name: Upload coverage to Codecov if: ${{ matrix.step == 'unit' }} - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v2.1.0 with: fail_ci_if_error: true @@ -65,11 +69,11 @@ jobs: strategy: matrix: - step: [lint-readme, pydocstyle] + step: [lintreadme, pydocstyle] env: - py-semver: 3.9 - TOXENV: ${{ format('py39-{0}', matrix.step) }} + py-semver: "3.10" + TOXENV: ${{ format('py310-{0}', matrix.step) }} steps: - uses: actions/checkout@v2 @@ -110,7 +114,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: "3.10" # quoted, otherwise that turns into the number 3.1 - name: Cache for pip uses: actions/cache@v2 diff --git a/MANIFEST.in b/MANIFEST.in index 6e775fd..74643c8 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ -include Makefile gittaggers.py test-requirements.txt mypy_requirements.txt requirements.txt +include Makefile gittaggers.py test-requirements.txt mypy-requirements.txt requirements.txt include cwltest/cwltest-schema.yml include cwltest/tests/* include cwltest/tests/test-data/* diff --git a/Makefile b/Makefile index abda48e..ea7110e 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ PACKAGE=cwltest PYSOURCES=$(wildcard ${MODULE}/**.py tests/*.py) setup.py DEVPKGS=diff_cover black pylint pep257 pydocstyle flake8 tox tox-pyenv \ isort wheel autoflake flake8-bugbear pyupgrade bandit \ - -rtest-requirements.txt -rmypy_requirements.txt + -rtest-requirements.txt -rmypy-requirements.txt DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage pydocstyle sloccount \ python-flake8 python-mock shellcheck VERSION=2.2.$(shell TZ=UTC git log --first-parent --max-count=1 \ diff --git a/cwltest/utils.py b/cwltest/utils.py index 984d8a8..50e1cb5 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -111,7 +111,7 @@ def check_keys(keys, expected, actual): except CompareFail as e: raise CompareFail.format( expected, actual, f"field '{k}' failed comparison: {str(e)}" - ) + ) from e def compare_file(expected, actual): @@ -159,7 +159,7 @@ def compare_dict(expected, actual): except CompareFail as e: raise CompareFail.format( expected, actual, f"failed comparison for key '{c}': {e}" - ) + ) from e extra_keys = set(actual.keys()).difference(list(expected.keys())) for k in extra_keys: if actual[k] is not None: @@ -194,13 +194,13 @@ def compare(expected, actual): # type: (Any, Any) -> None try: compare(expected[c], actual[c]) except CompareFail as e: - raise CompareFail.format(expected, actual, e) + raise CompareFail.format(expected, actual, e) from e else: if expected != actual: raise CompareFail.format(expected, actual) except Exception as e: - raise CompareFail(str(e)) + raise CompareFail(str(e)) from e def get_test_number_by_key(tests, key, value): diff --git a/mypy_requirements.txt b/mypy-requirements.txt similarity index 100% rename from mypy_requirements.txt rename to mypy-requirements.txt diff --git a/release-test.sh b/release-test.sh index dcb6d90..e840392 100755 --- a/release-test.sh +++ b/release-test.sh @@ -7,6 +7,8 @@ export LC_ALL=C package=cwltest module=cwltest +extras="" + if [ "$GITHUB_ACTIONS" = "true" ]; then # We are running as a GH Action repo=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git @@ -16,8 +18,8 @@ else HEAD=$(git rev-parse HEAD) fi run_tests="bin/py.test --pyargs ${module}" -pipver=20.3b1 # minimum required version of pip for Python 3.9 -setuptoolsver=41.1.0 # required for Python 3.9 +pipver=20.3.3 # minimum required version of pip for Python 3.10 +setuptoolsver=50.0.0 # required for Python 3.10 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" rm -Rf testenv? || /bin/true @@ -33,7 +35,7 @@ then rm -f testenv1/lib/python-wheels/setuptools* \ && pip install --force-reinstall -U pip==${pipver} \ && pip install setuptools==${setuptoolsver} wheel - pip install -rtest-requirements.txt + pip install -rtest-requirements.txt ".${extras}" make test pip uninstall -y ${package} || true; pip uninstall -y ${package} || true; make install mkdir testenv1/not-${module} @@ -59,7 +61,7 @@ rm -f lib/python-wheels/setuptools* \ && pip install --force-reinstall -U pip==${pipver} \ && pip install setuptools==${setuptoolsver} wheel # The following can fail if you haven't pushed your commits to ${repo} -pip install -e "git+${repo}@${HEAD}#egg=${package}" +pip install -e "git+${repo}@${HEAD}#egg=${package}${extras}" pushd src/${package} pip install -rtest-requirements.txt make dist @@ -83,13 +85,13 @@ rm -f lib/python-wheels/setuptools* \ && pip install setuptools==${setuptoolsver} wheel package_tar=$(find . -name "${package}*tar.gz") pip install "-r${DIR}/test-requirements.txt" -pip install "${package_tar}" +pip install "${package_tar}${extras}" mkdir out tar --extract --directory=out -z -f ${package}*.tar.gz pushd out/${package}* make dist make test -pip install "-r${DIR}/mypy_requirements.txt" +pip install "-r${DIR}/mypy-requirements.txt" make mypy pip uninstall -y ${package} || true; pip uninstall -y ${package} || true; make install mkdir ../not-${module} @@ -107,7 +109,7 @@ source bin/activate rm -f lib/python-wheels/setuptools* \ && pip install --force-reinstall -U pip==${pipver} \ && pip install setuptools==${setuptoolsver} wheel -pip install ${module}*.whl +pip install "$(ls ${module}*.whl)${extras}" pip install "-r${DIR}/test-requirements.txt" mkdir not-${module} pushd not-${module} diff --git a/setup.py b/setup.py index bb098fb..9c1d31b 100644 --- a/setup.py +++ b/setup.py @@ -61,6 +61,7 @@ "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Typing :: Typed", ], ) diff --git a/tox.ini b/tox.ini index 52e21a3..82b219b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,14 +1,13 @@ [tox] envlist = - py{36,37,38,39}-lint, - py{36,37,38,39}-unit, - py{36,37,38,39}-bandit, - py{36,37,38,39}-mypy, + py{36,37,38,39,310}-lint, + py{36,37,38,39,310}-unit, + py{36,37,38,39,310}-bandit, + py{36,37,38,39,310}-mypy, py39-pipconflictchecker, - py39-lint-readme, + py39-lintreadme, py39-pydocstyle -skipsdist = True skip_missing_interpreters = True [pytest] @@ -21,42 +20,48 @@ python = 3.7: py37 3.8: py38 3.9: py39 + 3.10: py310 [testenv] description = - py{36,37,38,39}-unit: Run the unit tests - py{36,37,38,39}-lint: Lint the Python code - py{36,37,38,39}-bandit: Search for common security issues - py{36,37,38,39}-mypy: Check for type safety + py{36,37,38,39,310}-unit: Run the unit tests + py{36,37,38,39,310}-lint: Lint the Python code + py{36,37,38,39,310}-bandit: Search for common security issues + py{36,37,38,39,310}-mypy: Check for type safety py39-pydocstyle: docstring style checker - py39-lint-readme: Lint the README.rst->.md conversion + py39-lintreadme: Lint the README.rst->.md conversion passenv = CI GITHUB_* deps = - py{36,37,38,39}-{unit,lint,bandit,mypy}: -rrequirements.txt - py{36,37,38,39}-{unit,mypy}: -rtest-requirements.txt - py{36,37,38,39}-lint: flake8-bugbear - py{36,37,38,39}-lint: black - py{36,37,38,39}-bandit: bandit - py{36,37,38,39}-mypy: -rmypy_requirements.txt + py{36,37,38,39,310}-{unit,mypy}: -rrequirements.txt + py{36,37,38,39,310}-{unit,mypy}: -rtest-requirements.txt + py{36,37,38,39,310}-lint: flake8-bugbear + py{36,37,38,39,310}-lint: black + py{36,37,38,39,310}-bandit: bandit + py{36,37,38,39,310}-mypy: -rmypy-requirements.txt setenv = - py{36,37,38,39}-unit: LC_ALL = C.UTF-8 + py{36,37,38,39,310}-unit: LC_ALL = C.UTF-8 commands = - py{36,37,38,39}-unit: python -m pip install -U pip setuptools wheel - py{36,37,38,39}-unit: make coverage-report coverage.xml PYTEST_EXTRA={posargs} - py{36,37,38,39}-bandit: bandit --recursive cwltest - py{36,37,38,39}-lint: make flake8 - py{36,37,38,39}-lint: make format-check - py{36,37,38,39}-mypy: make mypy + py{36,37,38,39,310}-unit: python -m pip install -U pip setuptools wheel + py{36,37,38,39,310}-unit: make coverage-report coverage.xml PYTEST_EXTRA={posargs} + py{36,37,38,39,310}-bandit: bandit --recursive cwltest --exclude cwltest/tests/* + py{36,37,38,39,310}-lint: make flake8 + py{36,37,38,39,310}-lint: make format-check + py{36,37,38,39,310}-mypy: make mypy whitelist_externals = - py{36,37,38,39}-lint: flake8 - py{36,37,38,39}-lint: black - py{36,37,38,39}-{mypy,shellcheck,lint,unit}: make + py{36,37,38,39,310}-lint: flake8 + py{36,37,38,39,310}-lint: black + py{36,37,38,39,310}-{mypy,shellcheck,lint,unit}: make + +skip_install = + py{36,37,38,39,310}-lint: true + py{36,37,38,39,310}-bandit: true + [testenv:py39-pydocstyle] whitelist_externals = make @@ -64,6 +69,7 @@ commands = make diff_pydocstyle_report deps = pydocstyle diff-cover +skip_install = true [testenv:py39-pipconflictchecker] commands = pipconflictchecker @@ -72,7 +78,8 @@ deps = pip-conflict-checker pip==9.0.3 -[testenv:py39-lint-readme] +[testenv:py39-lintreadme] +description = Lint the README.rst->.md conversion commands = python setup.py sdist python setup.py bdist_wheel @@ -81,3 +88,4 @@ deps = twine wheel readme_renderer[md] +skip_install = true From 91e655b8ef98f96d81be47f94e9ebc075b4470ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Dec 2021 00:31:17 +0000 Subject: [PATCH 020/165] Bump mypy from 0.910 to 0.920 Bumps [mypy](https://github.com/python/mypy) from 0.910 to 0.920. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.910...v0.920) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index e33b163..88051cf 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,3 +1,3 @@ -mypy==0.910 +mypy==0.920 types-setuptools types-requests From 4c567337ce5bbe78f28e92e2d2fb6dc3c445c94f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Dec 2021 00:24:45 +0000 Subject: [PATCH 021/165] Bump mypy from 0.920 to 0.921 Bumps [mypy](https://github.com/python/mypy) from 0.920 to 0.921. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.920...v0.921) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 88051cf..b84679c 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,3 +1,3 @@ -mypy==0.920 +mypy==0.921 types-setuptools types-requests From ad0089ff08ec6ae03f23c51234422ad23d713894 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Dec 2021 00:18:39 +0000 Subject: [PATCH 022/165] Bump mypy from 0.921 to 0.930 Bumps [mypy](https://github.com/python/mypy) from 0.921 to 0.930. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.921...v0.930) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index b84679c..f2b31ba 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,3 +1,3 @@ -mypy==0.921 +mypy==0.930 types-setuptools types-requests From d331e526e4e8c69b6d44b59309c38dfe1efe98fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jan 2022 00:53:36 +0000 Subject: [PATCH 023/165] Bump mypy from 0.930 to 0.931 Bumps [mypy](https://github.com/python/mypy) from 0.930 to 0.931. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.930...v0.931) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index f2b31ba..9ea607e 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,3 +1,3 @@ -mypy==0.930 +mypy==0.931 types-setuptools types-requests From 6ad17026863eccf1f1a57858e54f95e436e222a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Feb 2022 00:49:06 +0000 Subject: [PATCH 024/165] Update pytest requirement from <6.3,>=6.2 to >=6.2,<7.1 Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/6.2.0...7.0.0) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- setup.py | 2 +- test-requirements.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 9eadc1f..a51fd20 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ schema-salad >= 5.0.20200220195218, < 9 junit-xml >= 1.8 -pytest < 7 +pytest < 8 defusedxml diff --git a/setup.py b/setup.py index 9c1d31b..4716d04 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ ] needs_pytest = {"pytest", "test", "ptr"}.intersection(sys.argv) -pytest_runner = ["pytest < 7", "pytest-runner"] if needs_pytest else [] +pytest_runner = ["pytest < 8", "pytest-runner"] if needs_pytest else [] setup( name="cwltest", diff --git a/test-requirements.txt b/test-requirements.txt index eb7dc7f..70724d7 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,2 +1,2 @@ -pytest >= 6.2, < 6.3 +pytest >= 6.2, < 7.1 pytest-cov From d4fd5efb82250824c92c47290631522fc93dd0ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Feb 2022 00:17:18 +0000 Subject: [PATCH 025/165] Update pytest requirement from <7 to <8 Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/6.2.0...7.0.0) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 4716d04..445d543 100644 --- a/setup.py +++ b/setup.py @@ -42,7 +42,7 @@ include_package_data=True, install_requires=install_requires, test_suite="tests", - tests_require=["pytest<7"], + tests_require=["pytest<8"], entry_points={ "console_scripts": [ "cwltest=cwltest:main", From f016448aeb3ae9b395d8631d8ef112edb17b8e8b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Mar 2022 00:44:40 +0000 Subject: [PATCH 026/165] Bump mypy from 0.931 to 0.940 Bumps [mypy](https://github.com/python/mypy) from 0.931 to 0.940. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.931...v0.940) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 9ea607e..6aace86 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,3 +1,3 @@ -mypy==0.931 +mypy==0.940 types-setuptools types-requests From 29ad114bd54e34a22f18e313e1793409620bd18a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Mar 2022 07:30:29 +0000 Subject: [PATCH 027/165] Update pytest requirement from <7.1,>=6.2 to >=6.2,<7.2 Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/6.2.0...7.1.0) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 70724d7..072f0cc 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,2 +1,2 @@ -pytest >= 6.2, < 7.1 +pytest >= 6.2, < 7.2 pytest-cov From 12485839c8ff83af9e0e7c6f77c07f9a5975a3dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Mar 2022 00:18:49 +0000 Subject: [PATCH 028/165] Bump mypy from 0.940 to 0.941 Bumps [mypy](https://github.com/python/mypy) from 0.940 to 0.941. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.940...v0.941) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 6aace86..4d047ad 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,3 +1,3 @@ -mypy==0.940 +mypy==0.941 types-setuptools types-requests From f7a635832d640507d38585fa853c00d8b1047c82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Mar 2022 00:19:45 +0000 Subject: [PATCH 029/165] Bump mypy from 0.941 to 0.942 Bumps [mypy](https://github.com/python/mypy) from 0.941 to 0.942. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.941...v0.942) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 4d047ad..990114f 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,3 +1,3 @@ -mypy==0.941 +mypy==0.942 types-setuptools types-requests From b5f5b96c5ebd27128f942dcda05d3be3cb7709a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Apr 2022 00:09:50 +0000 Subject: [PATCH 030/165] Bump mypy from 0.942 to 0.950 Bumps [mypy](https://github.com/python/mypy) from 0.942 to 0.950. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.942...v0.950) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 990114f..ef46782 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,3 +1,3 @@ -mypy==0.942 +mypy==0.950 types-setuptools types-requests From c2f9c45223c67f953ecfc0d944dc68914b677f20 Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Sat, 14 May 2022 08:59:52 +0000 Subject: [PATCH 031/165] Add `sould_fail.default` to the schema --- cwltest/cwltest-schema.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cwltest/cwltest-schema.yml b/cwltest/cwltest-schema.yml index e084a75..3d40c7c 100644 --- a/cwltest/cwltest-schema.yml +++ b/cwltest/cwltest-schema.yml @@ -21,6 +21,8 @@ $graph: type: string? jsonldPredicate: _type: "@id" - should_fail: boolean? + should_fail: + type: boolean? + default: false output: type: Any? From 9dac068b7c163b26be1686981e2125bf8eb1955d Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Sat, 21 May 2022 19:30:21 +0900 Subject: [PATCH 032/165] Print `doc` field in one line (#136) --- cwltest/__init__.py | 27 +++++++++++++++------ cwltest/tests/test-data/multi-lined-doc.yml | 15 ++++++++++++ cwltest/tests/test_multi_lined_doc.py | 20 +++++++++++++++ 3 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 cwltest/tests/test-data/multi-lined-doc.yml create mode 100644 cwltest/tests/test_multi_lined_doc.py diff --git a/cwltest/__init__.py b/cwltest/__init__.py index 9e0ec7a..b400af4 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -127,14 +127,20 @@ def run_test( test_number, total_tests, test.get("short_name"), - test.get("doc"), + test.get("doc", "").replace("\n", " ").strip(), suffix, ) ) else: sys.stderr.write( "%sTest [%i/%i] %s%s\n" - % (prefix, test_number, total_tests, test.get("doc"), suffix) + % ( + prefix, + test_number, + total_tests, + test.get("doc", "").replace("\n", " ").strip(), + suffix, + ) ) if verbose: sys.stderr.write(f"Running: {' '.join(test_command)}\n") @@ -174,7 +180,7 @@ def run_test( test_number, " ".join([quote(tc) for tc in test_command]), ) - _logger.error(test.get("doc")) + _logger.error(test.get("doc", "").replace("\n", " ").strip()) if err.returncode == UNSUPPORTED_FEATURE: _logger.error("Does not support required feature") else: @@ -203,7 +209,7 @@ def run_test( test_number, " ".join([quote(tc) for tc in test_command]), ) - _logger.error(test.get("doc")) + _logger.error(test.get("doc", "").replace("\n", " ").strip()) # Kill and re-communicate to get the logs and reap the child, as # instructed in the subprocess docs. if process: @@ -229,7 +235,7 @@ def run_test( test_number, " ".join([quote(tc) for tc in test_command]), ) - _logger.warning(test.get("doc")) + _logger.warning(test.get("doc", "").replace("\n", " ").strip()) _logger.warning("Returned zero but it should be non-zero") return TestResult(1, outstr, outerr, duration, args.classname) @@ -241,7 +247,7 @@ def run_test( test_number, " ".join([quote(tc) for tc in test_command]), ) - _logger.warning(test.get("doc")) + _logger.warning(test.get("doc", "").replace("\n", " ").strip()) _logger.warning("Compare failure %s", ex) fail_message = str(ex) @@ -456,10 +462,15 @@ def main(): # type: () -> int for i, t in enumerate(tests): if t.get("short_name"): print( - "[%i] %s: %s" % (i + 1, t["short_name"], t.get("doc", "").strip()) + "[%i] %s: %s" + % ( + i + 1, + t["short_name"], + t.get("doc", "").replace("\n", " ").strip(), + ) ) else: - print("[%i] %s" % (i + 1, t.get("doc", "").strip())) + print("[%i] %s" % (i + 1, t.get("doc", "").replace("\n", " ").strip())) return 0 diff --git a/cwltest/tests/test-data/multi-lined-doc.yml b/cwltest/tests/test-data/multi-lined-doc.yml new file mode 100644 index 0000000..af21928 --- /dev/null +++ b/cwltest/tests/test-data/multi-lined-doc.yml @@ -0,0 +1,15 @@ +- job: v1.0/cat-job.json + output: {} + tool: return-0.cwl + doc: | + Test with + label + label: opt-error + tags: [ js, init_work_dir ] +- job: v1.0/cat-job.json + output: {} + tool: return-0.cwl + doc: | + Test without + label + tags: [ js, init_work_dir ] diff --git a/cwltest/tests/test_multi_lined_doc.py b/cwltest/tests/test_multi_lined_doc.py new file mode 100644 index 0000000..1fa1501 --- /dev/null +++ b/cwltest/tests/test_multi_lined_doc.py @@ -0,0 +1,20 @@ +import os +from os import linesep as n +from pathlib import Path + +from .util import run_with_mock_cwl_runner, get_data +import defusedxml.ElementTree as ET + + +def test_run(): + args = ["--test", get_data("tests/test-data/multi-lined-doc.yml")] + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + assert f"Test [1/2] opt-error: Test with label{n}" in stderr + assert f"Test [2/2] Test without label{n}" in stderr + + +def test_list(): + args = ["--test", get_data("tests/test-data/multi-lined-doc.yml"), "-l"] + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + assert f"[1] opt-error: Test with label{n}" in stdout + assert f"[2] Test without label{n}" in stdout From 4e842e80fff29f23a69572bcfbe08ebacbb37cbd Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Sat, 21 May 2022 22:18:28 +0900 Subject: [PATCH 033/165] Support string `id` field (#137) --- cwltest/__init__.py | 13 +++++++++++++ cwltest/tests/test-data/string-id.yml | 5 +++++ cwltest/tests/test_string_id.py | 12 ++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 cwltest/tests/test-data/string-id.yml create mode 100644 cwltest/tests/test_string_id.py diff --git a/cwltest/__init__.py b/cwltest/__init__.py index b400af4..f5e61f9 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -4,6 +4,7 @@ import json import logging import os +import re import shutil import subprocess # nosec import sys @@ -41,6 +42,16 @@ templock = threading.Lock() +def shortname( + name, # type: str +): # type: (...) -> str + """ + Return the short name of a given name. + It is a workaround of https://github.com/common-workflow-language/schema_salad/issues/511. + """ + return [n for n in re.split("[/#]", name) if len(n)][-1] + + def prepare_test_command( tool, # type: str args, # type: List[str] @@ -448,6 +459,8 @@ def main(): # type: () -> int for t in tests: if t.get("label"): t["short_name"] = t["label"] + elif t.get("id") and isinstance(t.get("id"), str): + t["short_name"] = shortname(t["id"]) if args.show_tags: alltags = set() # type: Set[str] diff --git a/cwltest/tests/test-data/string-id.yml b/cwltest/tests/test-data/string-id.yml new file mode 100644 index 0000000..0fd21eb --- /dev/null +++ b/cwltest/tests/test-data/string-id.yml @@ -0,0 +1,5 @@ +- job: v1.0/cat1-job.json + output: {} + tool: return-0.cwl + doc: Test with a string label + id: test-string-id diff --git a/cwltest/tests/test_string_id.py b/cwltest/tests/test_string_id.py new file mode 100644 index 0000000..77180ae --- /dev/null +++ b/cwltest/tests/test_string_id.py @@ -0,0 +1,12 @@ +import os +from os import linesep as n +from pathlib import Path + +from .util import run_with_mock_cwl_runner, get_data +import defusedxml.ElementTree as ET + + +def test_list(): + args = ["--test", get_data("tests/test-data/string-id.yml"), "-l"] + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + assert f"[1] test-string-id: Test with a string label{n}" in stdout From 0c8e5ab13310a9984a1386d65534f7dce0b1a7e4 Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Sat, 21 May 2022 15:00:03 +0000 Subject: [PATCH 034/165] Add `--exclude-tags` option --- cwltest/__init__.py | 12 +++++++++ cwltest/tests/test-data/exclude-tags.yml | 24 +++++++++++++++++ cwltest/tests/test_exclude_tags.py | 33 ++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 cwltest/tests/test-data/exclude-tags.yml create mode 100644 cwltest/tests/test_exclude_tags.py diff --git a/cwltest/__init__.py b/cwltest/__init__.py index f5e61f9..f89f413 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -317,6 +317,9 @@ def arg_parser(): # type: () -> argparse.ArgumentParser "--only-tools", action="https://github.com/store_true", help="Only test CommandLineTools" ) parser.add_argument("--tags", type=str, default=None, help="Tags to be tested") + parser.add_argument( + "--exclude-tags", type=str, default=None, help="Tags not to be tested" + ) parser.add_argument("--show-tags", action="https://github.com/store_true", help="Show all Tags.") parser.add_argument( "--junit-xml", type=str, default=None, help="Path to JUnit xml file" @@ -456,6 +459,15 @@ def main(): # type: () -> int if any(tag in ts for tag in tags): tests.append(t) + if args.exclude_tags: + ex_tests = [] + tags = args.exclude_tags.split(",") + for t in tests: + ts = t.get("tags", []) + if all(tag not in ts for tag in tags): + ex_tests.append(t) + tests = ex_tests + for t in tests: if t.get("label"): t["short_name"] = t["label"] diff --git a/cwltest/tests/test-data/exclude-tags.yml b/cwltest/tests/test-data/exclude-tags.yml new file mode 100644 index 0000000..106d5c2 --- /dev/null +++ b/cwltest/tests/test-data/exclude-tags.yml @@ -0,0 +1,24 @@ +- job: v1.0/cat-job.json + output: {} + tool: return-0.cwl + doc: | + Test with + label + id: opt-error1 + tags: [ command_line_tool ] +- job: v1.0/cat-job.json + id: opt-error2 + output: {} + tool: return-0.cwl + doc: | + Test without + label + tags: [ command_line_tool, workflow ] +- job: v1.0/cat-job.json + id: opt-error3 + output: {} + tool: return-0.cwl + doc: | + Test without + label + tags: [ workflow ] diff --git a/cwltest/tests/test_exclude_tags.py b/cwltest/tests/test_exclude_tags.py new file mode 100644 index 0000000..db01989 --- /dev/null +++ b/cwltest/tests/test_exclude_tags.py @@ -0,0 +1,33 @@ +import os +from os import linesep as n +from pathlib import Path + +from .util import run_with_mock_cwl_runner, get_data +import defusedxml.ElementTree as ET + + +def test_list_only_exclude(): + args = [ + "--test", + get_data("tests/test-data/exclude-tags.yml"), + "-l", + "--exclude-tags=workflow", + ] + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + assert f"[1] opt-error1: Test with label{n}" in stdout + assert "opt-error2" not in stdout + assert "opt-error3" not in stdout + + +def test_list_include_and_exclude(): + args = [ + "--test", + get_data("tests/test-data/exclude-tags.yml"), + "-l", + "--tags=command_line_tool", + "--exclude-tags=workflow", + ] + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + assert f"[1] opt-error1: Test with label{n}" in stdout + assert "opt-error2" not in stdout + assert "opt-error3" not in stdout From f78337498db51bf1ac806147a9e811940fda9c89 Mon Sep 17 00:00:00 2001 From: "Bruno P. Kinoshita" Date: Sun, 22 May 2022 22:03:29 +1200 Subject: [PATCH 035/165] Update Python versions tested on README --- .github/workflows/ci-tests.yml | 1 + README.rst | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 573fb61..97fab80 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -19,6 +19,7 @@ jobs: strategy: matrix: + # The README.rst file mentions the versions tested, please update it as well py-ver-major: [3] py-ver-minor: [6, 7, 8, 9, 10] step: [lint, unit, mypy] diff --git a/README.rst b/README.rst index bd0df40..e93d862 100644 --- a/README.rst +++ b/README.rst @@ -32,7 +32,7 @@ This is a testing tool for checking the output of Tools and Workflows described with the Common Workflow Language. Among other uses, it is used to run the CWL conformance tests. -This is written and tested for Python 3.6, 3.7, 3.8, and 3.9 +This is written and tested for Python 3.6, 3.7, 3.8, 3.9, and 3.10. Install ------- From b65f9b79d714c51547b1dd5e56b8e1affa0e1dd3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 May 2022 01:02:59 +0000 Subject: [PATCH 036/165] Bump mypy from 0.950 to 0.960 Bumps [mypy](https://github.com/python/mypy) from 0.950 to 0.960. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.950...v0.960) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index ef46782..3ee89b2 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,3 +1,3 @@ -mypy==0.950 +mypy==0.960 types-setuptools types-requests From 9672fa57bafa375994ab78bd77b492c636eec257 Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Mon, 30 May 2022 16:44:42 +0900 Subject: [PATCH 037/165] Add strict schema (#138) --- cwltest/cwltest-schema-strict.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 cwltest/cwltest-schema-strict.yml diff --git a/cwltest/cwltest-schema-strict.yml b/cwltest/cwltest-schema-strict.yml new file mode 100644 index 0000000..3ce52dd --- /dev/null +++ b/cwltest/cwltest-schema-strict.yml @@ -0,0 +1,27 @@ +$base: "https://w3id.org/cwl/cwltest#" +$graph: + - name: TestCase + type: record + documentRoot: true + fields: + id: + type: string + jsonldPredicate: + _type: "@id" + identity: true + short_name: string? + doc: string? + tags: string[] + tool: + type: string + jsonldPredicate: + _type: "@id" + job: + type: string? + jsonldPredicate: + _type: "@id" + should_fail: + type: boolean? + default: false + output: + type: Any? From 7fc2297b23246e981acfbab54ed01f4a8c55d6f1 Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Mon, 30 May 2022 23:20:12 +0900 Subject: [PATCH 038/165] Add deprecation messages (#141) --- cwltest/__init__.py | 12 ++++++++++-- cwltest/tests/test-data/integer-id.yml | 5 +++++ cwltest/tests/test_categories.py | 3 +++ cwltest/tests/test_integer_id.py | 19 +++++++++++++++++++ cwltest/tests/test_multi_lined_doc.py | 1 + 5 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 cwltest/tests/test-data/integer-id.yml create mode 100644 cwltest/tests/test_integer_id.py diff --git a/cwltest/__init__.py b/cwltest/__init__.py index f89f413..5a63b77 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -470,9 +470,17 @@ def main(): # type: () -> int for t in tests: if t.get("label"): + _logger.warning("The `label` field is deprecated. Use `id` field instead.") t["short_name"] = t["label"] - elif t.get("id") and isinstance(t.get("id"), str): - t["short_name"] = shortname(t["id"]) + elif t.get("id"): + if isinstance(t.get("id"), str): + t["short_name"] = shortname(t["id"]) + else: + _logger.warning( + "The `id` field with integer is deprecated. Use string identifier instead." + ) + else: + _logger.warning("The `id` field is missing.") if args.show_tags: alltags = set() # type: Set[str] diff --git a/cwltest/tests/test-data/integer-id.yml b/cwltest/tests/test-data/integer-id.yml new file mode 100644 index 0000000..8223cef --- /dev/null +++ b/cwltest/tests/test-data/integer-id.yml @@ -0,0 +1,5 @@ +- job: v1.0/cat1-job.json + output: {} + tool: return-0.cwl + doc: Test with an integer id + id: 1 diff --git a/cwltest/tests/test_categories.py b/cwltest/tests/test_categories.py index 77e8711..9da4e30 100644 --- a/cwltest/tests/test_categories.py +++ b/cwltest/tests/test_categories.py @@ -31,6 +31,8 @@ def test_unsupported_with_required_tests(): else: q = "" assert ( + "The `id` field is missing.{n}" + "The `id` field is missing.{n}" "Test [1/2] Required test that is unsupported (without tags){n}" "{n}" "Test 1 failed: mock-cwl-runner --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" @@ -57,6 +59,7 @@ def test_unsupported_with_optional_tests(): error_code, stdout, stderr = run_with_mock_cwl_runner(args) assert error_code == 0 assert ( + "The `id` field is missing.{n}" "Test [1/1] Optional test that is unsupported{n}{n}" "0 tests passed, 1 unsupported " "features{n}".format(n=n) diff --git a/cwltest/tests/test_integer_id.py b/cwltest/tests/test_integer_id.py new file mode 100644 index 0000000..7993111 --- /dev/null +++ b/cwltest/tests/test_integer_id.py @@ -0,0 +1,19 @@ +import os +from os import linesep as n +from pathlib import Path + +from .util import run_with_mock_cwl_runner, get_data +import defusedxml.ElementTree as ET + + +def test_warning_with_integer_id(): + args = [ + "--test", + get_data("tests/test-data/integer-id.yml"), + "-l", + ] + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + assert ( + "The `id` field with integer is deprecated. Use string identifier instead." + in stderr + ) diff --git a/cwltest/tests/test_multi_lined_doc.py b/cwltest/tests/test_multi_lined_doc.py index 1fa1501..9b6f4b3 100644 --- a/cwltest/tests/test_multi_lined_doc.py +++ b/cwltest/tests/test_multi_lined_doc.py @@ -9,6 +9,7 @@ def test_run(): args = ["--test", get_data("tests/test-data/multi-lined-doc.yml")] error_code, stdout, stderr = run_with_mock_cwl_runner(args) + assert "The `label` field is deprecated. Use `id` field instead." in stderr assert f"Test [1/2] opt-error: Test with label{n}" in stderr assert f"Test [2/2] Test without label{n}" in stderr From 4d60453ace928624bc2a241d8d32919cffa180f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Sep 2022 00:11:20 +0000 Subject: [PATCH 039/165] Bump mypy from 0.960 to 0.981 Bumps [mypy](https://github.com/python/mypy) from 0.960 to 0.981. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.960...v0.981) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 3ee89b2..7678736 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,3 +1,3 @@ -mypy==0.960 +mypy==0.981 types-setuptools types-requests From 678b401b4b155c5f5bc0bd3767c39fed3895021f Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Tue, 27 Sep 2022 11:06:45 +0200 Subject: [PATCH 040/165] make mypy_3.6: Still check the types in a Python 3.6 context, but using Py 3.7+ --- .github/workflows/ci-tests.yml | 4 ++++ Makefile | 9 +++++++++ tox.ini | 9 +++++---- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 97fab80..9ea22be 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -23,6 +23,10 @@ jobs: py-ver-major: [3] py-ver-minor: [6, 7, 8, 9, 10] step: [lint, unit, mypy] + exclude: + - py-ver-major: 3 + py-ver-minor: 6 + step: mypy env: py-semver: ${{ format('{0}.{1}', matrix.py-ver-major, matrix.py-ver-minor) }} diff --git a/Makefile b/Makefile index ea7110e..a807129 100644 --- a/Makefile +++ b/Makefile @@ -161,6 +161,15 @@ mypy: $(filter-out setup.py gittagger.py,$(PYSOURCES)) fi # if minimally required ruamel.yaml version is 0.15.99 or greater, than the above can be removed MYPYPATH=$$MYPYPATH:typeshed mypy $^ +mypy_3.6: $(filter-out setup.py gittagger.py,$(PYSOURCES)) + if ! test -f $(shell python3 -c 'import ruamel.yaml; import os.path; print(os.path.dirname(ruamel.yaml.__file__))')/py.typed ; \ + then \ + rm -Rf typeshed/ruamel/yaml ; \ + ln -s $(shell python3 -c 'import ruamel.yaml; import os.path; print(os.path.dirname(ruamel.yaml.__file__))') \ + typeshed/ruamel/ ; \ + fi # if minimally required ruamel.yaml version is 0.15.99 or greater, than the above can be removed + MYPYPATH=$$MYPYPATH:typeshed mypy --python-version 3.6 $^ + pyupgrade: $(filter-out schema_salad/metaschema.py,$(PYSOURCES)) pyupgrade --exit-zero-even-if-changed --py36-plus $^ diff --git a/tox.ini b/tox.ini index 82b219b..430d084 100644 --- a/tox.ini +++ b/tox.ini @@ -3,7 +3,7 @@ envlist = py{36,37,38,39,310}-lint, py{36,37,38,39,310}-unit, py{36,37,38,39,310}-bandit, - py{36,37,38,39,310}-mypy, + py{37,38,39,310}-mypy, py39-pipconflictchecker, py39-lintreadme, py39-pydocstyle @@ -27,7 +27,7 @@ description = py{36,37,38,39,310}-unit: Run the unit tests py{36,37,38,39,310}-lint: Lint the Python code py{36,37,38,39,310}-bandit: Search for common security issues - py{36,37,38,39,310}-mypy: Check for type safety + py{37,38,39,310}-mypy: Check for type safety py39-pydocstyle: docstring style checker py39-lintreadme: Lint the README.rst->.md conversion @@ -40,7 +40,7 @@ deps = py{36,37,38,39,310}-lint: flake8-bugbear py{36,37,38,39,310}-lint: black py{36,37,38,39,310}-bandit: bandit - py{36,37,38,39,310}-mypy: -rmypy-requirements.txt + py{37,38,39,310}-mypy: -rmypy-requirements.txt setenv = py{36,37,38,39,310}-unit: LC_ALL = C.UTF-8 @@ -51,7 +51,8 @@ commands = py{36,37,38,39,310}-bandit: bandit --recursive cwltest --exclude cwltest/tests/* py{36,37,38,39,310}-lint: make flake8 py{36,37,38,39,310}-lint: make format-check - py{36,37,38,39,310}-mypy: make mypy + py{37,38,39,310}-mypy: make mypy + py37-mypy: make mypy_3.6 whitelist_externals = py{36,37,38,39,310}-lint: flake8 From 733b6a71b695d039e9c9738654392a8b21775ece Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Tue, 27 Sep 2022 11:22:35 +0200 Subject: [PATCH 041/165] move type stubs out of protected name --- MANIFEST.in | 2 +- Makefile | 12 +- cwltest/__init__.py | 2 +- .../cachecontrol/__init__.pyi | 3 +- mypy-stubs/cachecontrol/cache.pyi | 5 + .../cachecontrol/caches/__init__.pyi | 4 +- mypy-stubs/cachecontrol/caches/file_cache.pyi | 31 + .../cachecontrol/compat.pyi | 2 +- mypy-stubs/cachecontrol/controller.pyi | 18 + mypy-stubs/cachecontrol/wrapper.pyi | 18 + mypy-stubs/junit_xml.pyi | 93 + mypy-stubs/rdflib/__init__.pyi | 32 + mypy-stubs/rdflib/collection.pyi | 19 + mypy-stubs/rdflib/compare.pyi | 10 + mypy-stubs/rdflib/graph.pyi | 252 +++ mypy-stubs/rdflib/namespace/_CSVW.pyi | 88 + mypy-stubs/rdflib/namespace/_DC.pyi | 20 + mypy-stubs/rdflib/namespace/_DCAT.pyi | 41 + mypy-stubs/rdflib/namespace/_DCTERMS.pyi | 101 + mypy-stubs/rdflib/namespace/_DOAP.pyi | 47 + mypy-stubs/rdflib/namespace/_FOAF.pyi | 80 + mypy-stubs/rdflib/namespace/_ODRL2.pyi | 209 +++ mypy-stubs/rdflib/namespace/_ORG.pyi | 50 + mypy-stubs/rdflib/namespace/_OWL.pyi | 82 + mypy-stubs/rdflib/namespace/_PROF.pyi | 15 + mypy-stubs/rdflib/namespace/_PROV.pyi | 175 ++ mypy-stubs/rdflib/namespace/_QB.pyi | 41 + mypy-stubs/rdflib/namespace/_RDF.pyi | 27 + mypy-stubs/rdflib/namespace/_RDFS.pyi | 20 + mypy-stubs/rdflib/namespace/_SDO.pyi | 1645 +++++++++++++++++ mypy-stubs/rdflib/namespace/_SH.pyi | 183 ++ mypy-stubs/rdflib/namespace/_SKOS.pyi | 37 + mypy-stubs/rdflib/namespace/_SOSA.pyi | 41 + mypy-stubs/rdflib/namespace/_SSN.pyi | 26 + mypy-stubs/rdflib/namespace/_TIME.pyi | 100 + mypy-stubs/rdflib/namespace/_VOID.pyi | 35 + mypy-stubs/rdflib/namespace/_XSD.pyi | 77 + mypy-stubs/rdflib/namespace/__init__.pyi | 85 + mypy-stubs/rdflib/parser.pyi | 5 + mypy-stubs/rdflib/paths.pyi | 24 + mypy-stubs/rdflib/plugin.pyi | 8 + .../rdflib/plugins/__init__.pyi | 1 - .../rdflib/plugins/parsers/__init__.pyi | 1 - .../rdflib/plugins/parsers/notation3.pyi | 1 + mypy-stubs/rdflib/query.pyi | 42 + mypy-stubs/rdflib/resource.pyi | 33 + mypy-stubs/rdflib/term.pyi | 43 + {typeshed => mypy-stubs}/ruamel/__init__.py | 0 typeshed/avro/__init__.pyi | 10 - typeshed/avro/schema.pyi | 117 -- typeshed/cachecontrol/adapter.pyi | 19 - typeshed/cachecontrol/cache.pyi | 19 - typeshed/cachecontrol/caches/file_cache.pyi | 22 - typeshed/cachecontrol/controller.pyi | 25 - typeshed/cachecontrol/filewrapper.pyi | 8 - typeshed/cachecontrol/serialize.pyi | 10 - typeshed/cachecontrol/wrapper.pyi | 14 - typeshed/future/__init__.pyi | 0 typeshed/future/utils/__init__.pyi | 61 - typeshed/galaxy/__init__.pyi | 13 - typeshed/galaxy/exceptions/__init__.pyi | 143 -- typeshed/galaxy/exceptions/error_codes.pyi | 17 - typeshed/galaxy/jobs/__init__.pyi | 4 - typeshed/galaxy/jobs/metrics/__init__.pyi | 38 - .../galaxy/jobs/metrics/collectl/__init__.pyi | 4 - typeshed/galaxy/jobs/metrics/collectl/cli.pyi | 12 - .../jobs/metrics/collectl/processes.pyi | 24 - .../galaxy/jobs/metrics/collectl/stats.pyi | 15 - .../jobs/metrics/collectl/subsystems.pyi | 35 - typeshed/galaxy/jobs/metrics/formatting.pyi | 8 - .../jobs/metrics/instrumenters/__init__.pyi | 16 - .../jobs/metrics/instrumenters/collectl.pyi | 22 - .../jobs/metrics/instrumenters/core.pyi | 18 - .../jobs/metrics/instrumenters/cpuinfo.pyi | 18 - .../galaxy/jobs/metrics/instrumenters/env.pyi | 18 - .../jobs/metrics/instrumenters/meminfo.pyi | 18 - .../jobs/metrics/instrumenters/uname.pyi | 18 - typeshed/galaxy/objectstore/__init__.pyi | 80 - typeshed/galaxy/objectstore/azure_blob.pyi | 29 - typeshed/galaxy/objectstore/pulsar.pyi | 24 - typeshed/galaxy/objectstore/rods.pyi | 32 - typeshed/galaxy/objectstore/s3.pyi | 34 - .../objectstore/s3_multipart_upload.pyi | 13 - typeshed/galaxy/tools/__init__.pyi | 4 - typeshed/galaxy/tools/cwl/__init__.pyi | 8 - typeshed/galaxy/tools/cwl/cwltool_deps.pyi | 22 - typeshed/galaxy/tools/cwl/parser.pyi | 94 - typeshed/galaxy/tools/cwl/representation.pyi | 12 - typeshed/galaxy/tools/cwl/runtime_actions.pyi | 7 - typeshed/galaxy/tools/cwl/schema.pyi | 22 - typeshed/galaxy/tools/deps/__init__.pyi | 41 - typeshed/galaxy/tools/deps/brew_exts.pyi | 74 - typeshed/galaxy/tools/deps/brew_util.pyi | 18 - typeshed/galaxy/tools/deps/commands.pyi | 22 - typeshed/galaxy/tools/deps/conda_compat.pyi | 21 - typeshed/galaxy/tools/deps/conda_util.pyi | 69 - .../deps/container_resolvers/__init__.pyi | 14 - .../deps/container_resolvers/explicit.pyi | 9 - .../tools/deps/container_resolvers/mulled.pyi | 55 - typeshed/galaxy/tools/deps/containers.pyi | 99 - typeshed/galaxy/tools/deps/dependencies.pyi | 13 - typeshed/galaxy/tools/deps/docker_util.pyi | 41 - typeshed/galaxy/tools/deps/dockerfiles.pyi | 15 - typeshed/galaxy/tools/deps/installable.pyi | 15 - .../galaxy/tools/deps/mulled/__init__.pyi | 4 - typeshed/galaxy/tools/deps/mulled/_cli.pyi | 5 - .../galaxy/tools/deps/mulled/mulled_build.pyi | 24 - .../deps/mulled/mulled_build_channel.pyi | 7 - .../tools/deps/mulled/mulled_build_files.pyi | 10 - .../tools/deps/mulled/mulled_build_tool.pyi | 8 - .../tools/deps/mulled/mulled_search.pyi | 23 - typeshed/galaxy/tools/deps/mulled/util.pyi | 23 - typeshed/galaxy/tools/deps/requirements.pyi | 75 - .../galaxy/tools/deps/resolvers/__init__.pyi | 62 - .../resolvers/brewed_tool_shed_packages.pyi | 33 - .../galaxy/tools/deps/resolvers/conda.pyi | 72 - .../tools/deps/resolvers/galaxy_packages.pyi | 35 - .../galaxy/tools/deps/resolvers/homebrew.pyi | 14 - .../galaxy/tools/deps/resolvers/modules.pyi | 42 - .../tools/deps/resolvers/resolver_mixins.pyi | 18 - .../deps/resolvers/tool_shed_packages.pyi | 13 - .../resolvers/unlinked_tool_shed_packages.pyi | 25 - .../galaxy/tools/deps/singularity_util.pyi | 7 - typeshed/galaxy/tools/deps/views.pyi | 32 - typeshed/galaxy/tools/fetcher.pyi | 10 - typeshed/galaxy/tools/lint.pyi | 33 - typeshed/galaxy/tools/lint_util.pyi | 5 - typeshed/galaxy/tools/linters/__init__.pyi | 4 - typeshed/galaxy/tools/linters/citations.pyi | 5 - typeshed/galaxy/tools/linters/command.pyi | 6 - typeshed/galaxy/tools/linters/cwl.pyi | 12 - typeshed/galaxy/tools/linters/general.pyi | 19 - typeshed/galaxy/tools/linters/help.pyi | 6 - typeshed/galaxy/tools/linters/inputs.pyi | 8 - typeshed/galaxy/tools/linters/outputs.pyi | 5 - typeshed/galaxy/tools/linters/stdio.pyi | 7 - typeshed/galaxy/tools/linters/tests.pyi | 7 - typeshed/galaxy/tools/linters/xml_order.pyi | 10 - typeshed/galaxy/tools/loader.pyi | 8 - typeshed/galaxy/tools/loader_directory.pyi | 15 - typeshed/galaxy/tools/locations/__init__.pyi | 7 - typeshed/galaxy/tools/locations/dockstore.pyi | 19 - typeshed/galaxy/tools/locations/file.pyi | 9 - typeshed/galaxy/tools/locations/http.pyi | 13 - typeshed/galaxy/tools/parser/__init__.pyi | 7 - typeshed/galaxy/tools/parser/cwl.pyi | 41 - typeshed/galaxy/tools/parser/factory.pyi | 9 - typeshed/galaxy/tools/parser/interface.pyi | 96 - .../galaxy/tools/parser/output_actions.pyi | 215 --- .../tools/parser/output_collection_def.pyi | 29 - .../galaxy/tools/parser/output_objects.pyi | 68 - typeshed/galaxy/tools/parser/util.pyi | 9 - typeshed/galaxy/tools/parser/xml.pyi | 89 - typeshed/galaxy/tools/parser/yaml.pyi | 56 - typeshed/galaxy/tools/verify/__init__.pyi | 18 - .../galaxy/tools/verify/asserts/__init__.pyi | 14 - .../galaxy/tools/verify/asserts/tabular.pyi | 6 - typeshed/galaxy/tools/verify/asserts/text.pyi | 9 - typeshed/galaxy/tools/verify/asserts/xml.pyi | 15 - typeshed/galaxy/tools/verify/test_data.pyi | 31 - typeshed/galaxy/util/__init__.pyi | 131 -- typeshed/galaxy/util/aliaspickler.pyi | 20 - typeshed/galaxy/util/bunch.pyi | 17 - typeshed/galaxy/util/checkers.pyi | 14 - typeshed/galaxy/util/compression_utils.pyi | 7 - typeshed/galaxy/util/dictifiable.pyi | 8 - typeshed/galaxy/util/expressions.pyi | 18 - typeshed/galaxy/util/filelock.pyi | 21 - typeshed/galaxy/util/hash_util.pyi | 14 - typeshed/galaxy/util/heartbeat.pyi | 30 - typeshed/galaxy/util/image_util.pyi | 13 - typeshed/galaxy/util/inflection.pyi | 46 - typeshed/galaxy/util/json.pyi | 12 - typeshed/galaxy/util/lazy_process.pyi | 22 - typeshed/galaxy/util/object_wrapper.pyi | 95 - typeshed/galaxy/util/odict.pyi | 27 - typeshed/galaxy/util/oset.pyi | 19 - typeshed/galaxy/util/plugin_config.pyi | 11 - typeshed/galaxy/util/properties.pyi | 19 - typeshed/galaxy/util/simplegraph.pyi | 26 - typeshed/galaxy/util/sleeper.pyi | 11 - typeshed/galaxy/util/sockets.pyi | 7 - typeshed/galaxy/util/specs.pyi | 9 - typeshed/galaxy/util/sqlite.pyi | 6 - typeshed/galaxy/util/submodules.pyi | 9 - typeshed/galaxy/util/topsort.pyi | 20 - typeshed/galaxy/util/xml_macros.pyi | 18 - typeshed/junit_xml.pyi | 60 - typeshed/mistune.pyi | 271 --- typeshed/rdflib/__init__.pyi | 9 - typeshed/rdflib/events.pyi | 12 - typeshed/rdflib/exceptions.pyi | 37 - typeshed/rdflib/graph.pyi | 159 -- typeshed/rdflib/namespace.pyi | 62 - typeshed/rdflib/parser.pyi | 10 - typeshed/rdflib/plugin.pyi | 28 - typeshed/rdflib/plugins/parsers/notation3.pyi | 12 - typeshed/rdflib/query.pyi | 54 - typeshed/rdflib/serializer.pyi | 13 - typeshed/rdflib/store.pyi | 48 - typeshed/rdflib/term.pyi | 87 - typeshed/rdflib/util.pyi | 21 - typeshed/select.pyi | 137 -- typeshed/shellescape/__init__.pyi | 5 - typeshed/shellescape/main.pyi | 5 - typeshed/urllib/__init__.py | 0 typeshed/urllib/parse.pyi | 152 -- typeshed/urllib/subprocess.pyi | 1208 ------------ 208 files changed, 3872 insertions(+), 6139 deletions(-) rename {typeshed => mypy-stubs}/cachecontrol/__init__.pyi (63%) create mode 100644 mypy-stubs/cachecontrol/cache.pyi rename {typeshed => mypy-stubs}/cachecontrol/caches/__init__.pyi (80%) create mode 100644 mypy-stubs/cachecontrol/caches/file_cache.pyi rename {typeshed => mypy-stubs}/cachecontrol/compat.pyi (83%) create mode 100644 mypy-stubs/cachecontrol/controller.pyi create mode 100644 mypy-stubs/cachecontrol/wrapper.pyi create mode 100644 mypy-stubs/junit_xml.pyi create mode 100644 mypy-stubs/rdflib/__init__.pyi create mode 100644 mypy-stubs/rdflib/collection.pyi create mode 100644 mypy-stubs/rdflib/compare.pyi create mode 100644 mypy-stubs/rdflib/graph.pyi create mode 100644 mypy-stubs/rdflib/namespace/_CSVW.pyi create mode 100644 mypy-stubs/rdflib/namespace/_DC.pyi create mode 100644 mypy-stubs/rdflib/namespace/_DCAT.pyi create mode 100644 mypy-stubs/rdflib/namespace/_DCTERMS.pyi create mode 100644 mypy-stubs/rdflib/namespace/_DOAP.pyi create mode 100644 mypy-stubs/rdflib/namespace/_FOAF.pyi create mode 100644 mypy-stubs/rdflib/namespace/_ODRL2.pyi create mode 100644 mypy-stubs/rdflib/namespace/_ORG.pyi create mode 100644 mypy-stubs/rdflib/namespace/_OWL.pyi create mode 100644 mypy-stubs/rdflib/namespace/_PROF.pyi create mode 100644 mypy-stubs/rdflib/namespace/_PROV.pyi create mode 100644 mypy-stubs/rdflib/namespace/_QB.pyi create mode 100644 mypy-stubs/rdflib/namespace/_RDF.pyi create mode 100644 mypy-stubs/rdflib/namespace/_RDFS.pyi create mode 100644 mypy-stubs/rdflib/namespace/_SDO.pyi create mode 100644 mypy-stubs/rdflib/namespace/_SH.pyi create mode 100644 mypy-stubs/rdflib/namespace/_SKOS.pyi create mode 100644 mypy-stubs/rdflib/namespace/_SOSA.pyi create mode 100644 mypy-stubs/rdflib/namespace/_SSN.pyi create mode 100644 mypy-stubs/rdflib/namespace/_TIME.pyi create mode 100644 mypy-stubs/rdflib/namespace/_VOID.pyi create mode 100644 mypy-stubs/rdflib/namespace/_XSD.pyi create mode 100644 mypy-stubs/rdflib/namespace/__init__.pyi create mode 100644 mypy-stubs/rdflib/parser.pyi create mode 100644 mypy-stubs/rdflib/paths.pyi create mode 100644 mypy-stubs/rdflib/plugin.pyi rename {typeshed => mypy-stubs}/rdflib/plugins/__init__.pyi (99%) rename {typeshed => mypy-stubs}/rdflib/plugins/parsers/__init__.pyi (99%) create mode 100644 mypy-stubs/rdflib/plugins/parsers/notation3.pyi create mode 100644 mypy-stubs/rdflib/query.pyi create mode 100644 mypy-stubs/rdflib/resource.pyi create mode 100644 mypy-stubs/rdflib/term.pyi rename {typeshed => mypy-stubs}/ruamel/__init__.py (100%) delete mode 100644 typeshed/avro/__init__.pyi delete mode 100644 typeshed/avro/schema.pyi delete mode 100644 typeshed/cachecontrol/adapter.pyi delete mode 100644 typeshed/cachecontrol/cache.pyi delete mode 100644 typeshed/cachecontrol/caches/file_cache.pyi delete mode 100644 typeshed/cachecontrol/controller.pyi delete mode 100644 typeshed/cachecontrol/filewrapper.pyi delete mode 100644 typeshed/cachecontrol/serialize.pyi delete mode 100644 typeshed/cachecontrol/wrapper.pyi delete mode 100644 typeshed/future/__init__.pyi delete mode 100644 typeshed/future/utils/__init__.pyi delete mode 100644 typeshed/galaxy/__init__.pyi delete mode 100644 typeshed/galaxy/exceptions/__init__.pyi delete mode 100644 typeshed/galaxy/exceptions/error_codes.pyi delete mode 100644 typeshed/galaxy/jobs/__init__.pyi delete mode 100644 typeshed/galaxy/jobs/metrics/__init__.pyi delete mode 100644 typeshed/galaxy/jobs/metrics/collectl/__init__.pyi delete mode 100644 typeshed/galaxy/jobs/metrics/collectl/cli.pyi delete mode 100644 typeshed/galaxy/jobs/metrics/collectl/processes.pyi delete mode 100644 typeshed/galaxy/jobs/metrics/collectl/stats.pyi delete mode 100644 typeshed/galaxy/jobs/metrics/collectl/subsystems.pyi delete mode 100644 typeshed/galaxy/jobs/metrics/formatting.pyi delete mode 100644 typeshed/galaxy/jobs/metrics/instrumenters/__init__.pyi delete mode 100644 typeshed/galaxy/jobs/metrics/instrumenters/collectl.pyi delete mode 100644 typeshed/galaxy/jobs/metrics/instrumenters/core.pyi delete mode 100644 typeshed/galaxy/jobs/metrics/instrumenters/cpuinfo.pyi delete mode 100644 typeshed/galaxy/jobs/metrics/instrumenters/env.pyi delete mode 100644 typeshed/galaxy/jobs/metrics/instrumenters/meminfo.pyi delete mode 100644 typeshed/galaxy/jobs/metrics/instrumenters/uname.pyi delete mode 100644 typeshed/galaxy/objectstore/__init__.pyi delete mode 100644 typeshed/galaxy/objectstore/azure_blob.pyi delete mode 100644 typeshed/galaxy/objectstore/pulsar.pyi delete mode 100644 typeshed/galaxy/objectstore/rods.pyi delete mode 100644 typeshed/galaxy/objectstore/s3.pyi delete mode 100644 typeshed/galaxy/objectstore/s3_multipart_upload.pyi delete mode 100644 typeshed/galaxy/tools/__init__.pyi delete mode 100644 typeshed/galaxy/tools/cwl/__init__.pyi delete mode 100644 typeshed/galaxy/tools/cwl/cwltool_deps.pyi delete mode 100644 typeshed/galaxy/tools/cwl/parser.pyi delete mode 100644 typeshed/galaxy/tools/cwl/representation.pyi delete mode 100644 typeshed/galaxy/tools/cwl/runtime_actions.pyi delete mode 100644 typeshed/galaxy/tools/cwl/schema.pyi delete mode 100644 typeshed/galaxy/tools/deps/__init__.pyi delete mode 100644 typeshed/galaxy/tools/deps/brew_exts.pyi delete mode 100644 typeshed/galaxy/tools/deps/brew_util.pyi delete mode 100644 typeshed/galaxy/tools/deps/commands.pyi delete mode 100644 typeshed/galaxy/tools/deps/conda_compat.pyi delete mode 100644 typeshed/galaxy/tools/deps/conda_util.pyi delete mode 100644 typeshed/galaxy/tools/deps/container_resolvers/__init__.pyi delete mode 100644 typeshed/galaxy/tools/deps/container_resolvers/explicit.pyi delete mode 100644 typeshed/galaxy/tools/deps/container_resolvers/mulled.pyi delete mode 100644 typeshed/galaxy/tools/deps/containers.pyi delete mode 100644 typeshed/galaxy/tools/deps/dependencies.pyi delete mode 100644 typeshed/galaxy/tools/deps/docker_util.pyi delete mode 100644 typeshed/galaxy/tools/deps/dockerfiles.pyi delete mode 100644 typeshed/galaxy/tools/deps/installable.pyi delete mode 100644 typeshed/galaxy/tools/deps/mulled/__init__.pyi delete mode 100644 typeshed/galaxy/tools/deps/mulled/_cli.pyi delete mode 100644 typeshed/galaxy/tools/deps/mulled/mulled_build.pyi delete mode 100644 typeshed/galaxy/tools/deps/mulled/mulled_build_channel.pyi delete mode 100644 typeshed/galaxy/tools/deps/mulled/mulled_build_files.pyi delete mode 100644 typeshed/galaxy/tools/deps/mulled/mulled_build_tool.pyi delete mode 100644 typeshed/galaxy/tools/deps/mulled/mulled_search.pyi delete mode 100644 typeshed/galaxy/tools/deps/mulled/util.pyi delete mode 100644 typeshed/galaxy/tools/deps/requirements.pyi delete mode 100644 typeshed/galaxy/tools/deps/resolvers/__init__.pyi delete mode 100644 typeshed/galaxy/tools/deps/resolvers/brewed_tool_shed_packages.pyi delete mode 100644 typeshed/galaxy/tools/deps/resolvers/conda.pyi delete mode 100644 typeshed/galaxy/tools/deps/resolvers/galaxy_packages.pyi delete mode 100644 typeshed/galaxy/tools/deps/resolvers/homebrew.pyi delete mode 100644 typeshed/galaxy/tools/deps/resolvers/modules.pyi delete mode 100644 typeshed/galaxy/tools/deps/resolvers/resolver_mixins.pyi delete mode 100644 typeshed/galaxy/tools/deps/resolvers/tool_shed_packages.pyi delete mode 100644 typeshed/galaxy/tools/deps/resolvers/unlinked_tool_shed_packages.pyi delete mode 100644 typeshed/galaxy/tools/deps/singularity_util.pyi delete mode 100644 typeshed/galaxy/tools/deps/views.pyi delete mode 100644 typeshed/galaxy/tools/fetcher.pyi delete mode 100644 typeshed/galaxy/tools/lint.pyi delete mode 100644 typeshed/galaxy/tools/lint_util.pyi delete mode 100644 typeshed/galaxy/tools/linters/__init__.pyi delete mode 100644 typeshed/galaxy/tools/linters/citations.pyi delete mode 100644 typeshed/galaxy/tools/linters/command.pyi delete mode 100644 typeshed/galaxy/tools/linters/cwl.pyi delete mode 100644 typeshed/galaxy/tools/linters/general.pyi delete mode 100644 typeshed/galaxy/tools/linters/help.pyi delete mode 100644 typeshed/galaxy/tools/linters/inputs.pyi delete mode 100644 typeshed/galaxy/tools/linters/outputs.pyi delete mode 100644 typeshed/galaxy/tools/linters/stdio.pyi delete mode 100644 typeshed/galaxy/tools/linters/tests.pyi delete mode 100644 typeshed/galaxy/tools/linters/xml_order.pyi delete mode 100644 typeshed/galaxy/tools/loader.pyi delete mode 100644 typeshed/galaxy/tools/loader_directory.pyi delete mode 100644 typeshed/galaxy/tools/locations/__init__.pyi delete mode 100644 typeshed/galaxy/tools/locations/dockstore.pyi delete mode 100644 typeshed/galaxy/tools/locations/file.pyi delete mode 100644 typeshed/galaxy/tools/locations/http.pyi delete mode 100644 typeshed/galaxy/tools/parser/__init__.pyi delete mode 100644 typeshed/galaxy/tools/parser/cwl.pyi delete mode 100644 typeshed/galaxy/tools/parser/factory.pyi delete mode 100644 typeshed/galaxy/tools/parser/interface.pyi delete mode 100644 typeshed/galaxy/tools/parser/output_actions.pyi delete mode 100644 typeshed/galaxy/tools/parser/output_collection_def.pyi delete mode 100644 typeshed/galaxy/tools/parser/output_objects.pyi delete mode 100644 typeshed/galaxy/tools/parser/util.pyi delete mode 100644 typeshed/galaxy/tools/parser/xml.pyi delete mode 100644 typeshed/galaxy/tools/parser/yaml.pyi delete mode 100644 typeshed/galaxy/tools/verify/__init__.pyi delete mode 100644 typeshed/galaxy/tools/verify/asserts/__init__.pyi delete mode 100644 typeshed/galaxy/tools/verify/asserts/tabular.pyi delete mode 100644 typeshed/galaxy/tools/verify/asserts/text.pyi delete mode 100644 typeshed/galaxy/tools/verify/asserts/xml.pyi delete mode 100644 typeshed/galaxy/tools/verify/test_data.pyi delete mode 100644 typeshed/galaxy/util/__init__.pyi delete mode 100644 typeshed/galaxy/util/aliaspickler.pyi delete mode 100644 typeshed/galaxy/util/bunch.pyi delete mode 100644 typeshed/galaxy/util/checkers.pyi delete mode 100644 typeshed/galaxy/util/compression_utils.pyi delete mode 100644 typeshed/galaxy/util/dictifiable.pyi delete mode 100644 typeshed/galaxy/util/expressions.pyi delete mode 100644 typeshed/galaxy/util/filelock.pyi delete mode 100644 typeshed/galaxy/util/hash_util.pyi delete mode 100644 typeshed/galaxy/util/heartbeat.pyi delete mode 100644 typeshed/galaxy/util/image_util.pyi delete mode 100644 typeshed/galaxy/util/inflection.pyi delete mode 100644 typeshed/galaxy/util/json.pyi delete mode 100644 typeshed/galaxy/util/lazy_process.pyi delete mode 100644 typeshed/galaxy/util/object_wrapper.pyi delete mode 100644 typeshed/galaxy/util/odict.pyi delete mode 100644 typeshed/galaxy/util/oset.pyi delete mode 100644 typeshed/galaxy/util/plugin_config.pyi delete mode 100644 typeshed/galaxy/util/properties.pyi delete mode 100644 typeshed/galaxy/util/simplegraph.pyi delete mode 100644 typeshed/galaxy/util/sleeper.pyi delete mode 100644 typeshed/galaxy/util/sockets.pyi delete mode 100644 typeshed/galaxy/util/specs.pyi delete mode 100644 typeshed/galaxy/util/sqlite.pyi delete mode 100644 typeshed/galaxy/util/submodules.pyi delete mode 100644 typeshed/galaxy/util/topsort.pyi delete mode 100644 typeshed/galaxy/util/xml_macros.pyi delete mode 100644 typeshed/junit_xml.pyi delete mode 100644 typeshed/mistune.pyi delete mode 100644 typeshed/rdflib/__init__.pyi delete mode 100644 typeshed/rdflib/events.pyi delete mode 100644 typeshed/rdflib/exceptions.pyi delete mode 100644 typeshed/rdflib/graph.pyi delete mode 100644 typeshed/rdflib/namespace.pyi delete mode 100644 typeshed/rdflib/parser.pyi delete mode 100644 typeshed/rdflib/plugin.pyi delete mode 100644 typeshed/rdflib/plugins/parsers/notation3.pyi delete mode 100644 typeshed/rdflib/query.pyi delete mode 100644 typeshed/rdflib/serializer.pyi delete mode 100644 typeshed/rdflib/store.pyi delete mode 100644 typeshed/rdflib/term.pyi delete mode 100644 typeshed/rdflib/util.pyi delete mode 100644 typeshed/select.pyi delete mode 100644 typeshed/shellescape/__init__.pyi delete mode 100644 typeshed/shellescape/main.pyi delete mode 100644 typeshed/urllib/__init__.py delete mode 100644 typeshed/urllib/parse.pyi delete mode 100644 typeshed/urllib/subprocess.pyi diff --git a/MANIFEST.in b/MANIFEST.in index 74643c8..f902163 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,6 +3,6 @@ include cwltest/cwltest-schema.yml include cwltest/tests/* include cwltest/tests/test-data/* include cwltest/tests/test-data/v1.0/* -recursive-include typeshed *.py? +recursive-include mypy-stubs *.py? global-exclude *~ global-exclude *.pyc diff --git a/Makefile b/Makefile index a807129..b655cd9 100644 --- a/Makefile +++ b/Makefile @@ -155,20 +155,20 @@ mypy3: mypy mypy: $(filter-out setup.py gittagger.py,$(PYSOURCES)) if ! test -f $(shell python3 -c 'import ruamel.yaml; import os.path; print(os.path.dirname(ruamel.yaml.__file__))')/py.typed ; \ then \ - rm -Rf typeshed/ruamel/yaml ; \ + rm -Rf mypy-stubs/ruamel/yaml ; \ ln -s $(shell python3 -c 'import ruamel.yaml; import os.path; print(os.path.dirname(ruamel.yaml.__file__))') \ - typeshed/ruamel/ ; \ + mypy-stubs/ruamel/ ; \ fi # if minimally required ruamel.yaml version is 0.15.99 or greater, than the above can be removed - MYPYPATH=$$MYPYPATH:typeshed mypy $^ + MYPYPATH=$$MYPYPATH:mypy-stubs mypy $^ mypy_3.6: $(filter-out setup.py gittagger.py,$(PYSOURCES)) if ! test -f $(shell python3 -c 'import ruamel.yaml; import os.path; print(os.path.dirname(ruamel.yaml.__file__))')/py.typed ; \ then \ - rm -Rf typeshed/ruamel/yaml ; \ + rm -Rf mypy-stubs/ruamel/yaml ; \ ln -s $(shell python3 -c 'import ruamel.yaml; import os.path; print(os.path.dirname(ruamel.yaml.__file__))') \ - typeshed/ruamel/ ; \ + mypy-stubs/ruamel/ ; \ fi # if minimally required ruamel.yaml version is 0.15.99 or greater, than the above can be removed - MYPYPATH=$$MYPYPATH:typeshed mypy --python-version 3.6 $^ + MYPYPATH=$$MYPYPATH:mypy-stubs mypy --python-version 3.6 $^ pyupgrade: $(filter-out schema_salad/metaschema.py,$(PYSOURCES)) pyupgrade --exit-zero-even-if-changed --py36-plus $^ diff --git a/cwltest/__init__.py b/cwltest/__init__.py index 5a63b77..e16c828 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -595,7 +595,7 @@ def main(): # type: () -> int if args.junit_xml: with open(args.junit_xml, "w") as xml: - junit_xml.TestSuite.to_file(xml, [report]) + junit_xml.to_xml_report_file(xml, [report]) if args.badgedir: os.mkdir(args.badgedir) diff --git a/typeshed/cachecontrol/__init__.pyi b/mypy-stubs/cachecontrol/__init__.pyi similarity index 63% rename from typeshed/cachecontrol/__init__.pyi rename to mypy-stubs/cachecontrol/__init__.pyi index dba67bc..d8c9745 100644 --- a/typeshed/cachecontrol/__init__.pyi +++ b/mypy-stubs/cachecontrol/__init__.pyi @@ -3,8 +3,7 @@ # NOTE: This dynamically typed stub was automatically generated by stubgen. from typing import Any + from .wrapper import CacheControl as CacheControl -#from .adapter import CacheControlAdapter as CacheControlAdapter -#from .controller import CacheController as CacheController __email__ = ... # type: Any diff --git a/mypy-stubs/cachecontrol/cache.pyi b/mypy-stubs/cachecontrol/cache.pyi new file mode 100644 index 0000000..f738f6f --- /dev/null +++ b/mypy-stubs/cachecontrol/cache.pyi @@ -0,0 +1,5 @@ +class BaseCache: + def get(self, key: str) -> bytes | None: ... + def set(self, key: str, value: bytes, expires: int | None = None) -> None: ... + def delete(self, key: str) -> None: ... + def close(self) -> None: ... diff --git a/typeshed/cachecontrol/caches/__init__.pyi b/mypy-stubs/cachecontrol/caches/__init__.pyi similarity index 80% rename from typeshed/cachecontrol/caches/__init__.pyi rename to mypy-stubs/cachecontrol/caches/__init__.pyi index b7784c2..42c0ad6 100644 --- a/typeshed/cachecontrol/caches/__init__.pyi +++ b/mypy-stubs/cachecontrol/caches/__init__.pyi @@ -3,7 +3,9 @@ # NOTE: This dynamically typed stub was automatically generated by stubgen. from typing import Any + from .file_cache import FileCache as FileCache -#from .redis_cache import RedisCache as RedisCache + +# from .redis_cache import RedisCache as RedisCache notice = ... # type: Any diff --git a/mypy-stubs/cachecontrol/caches/file_cache.pyi b/mypy-stubs/cachecontrol/caches/file_cache.pyi new file mode 100644 index 0000000..a89d758 --- /dev/null +++ b/mypy-stubs/cachecontrol/caches/file_cache.pyi @@ -0,0 +1,31 @@ +from os import PathLike +from typing import ContextManager + +from ..cache import BaseCache as BaseCache +from ..controller import CacheController as CacheController + +class _LockClass: + path: str + +_lock_class = ContextManager[_LockClass] + +class FileCache(BaseCache): + directory: str + forever: bool + filemode: int + dirmode: int + lock_class: _lock_class | None = None + def __init__( + self, + directory: str | PathLike[str], + forever: bool = ..., + filemode: int = ..., + dirmode: int = ..., + use_dir_lock: bool | None = ..., + lock_class: _lock_class | None = ..., + ) -> None: ... + @staticmethod + def encode(x: str) -> str: ... + def get(self, key: str) -> None | bytes: ... + def set(self, key: str, value: bytes, expires: int | None = None) -> None: ... + def delete(self, key: str) -> None: ... diff --git a/typeshed/cachecontrol/compat.pyi b/mypy-stubs/cachecontrol/compat.pyi similarity index 83% rename from typeshed/cachecontrol/compat.pyi rename to mypy-stubs/cachecontrol/compat.pyi index 0926ecc..fabfae3 100644 --- a/typeshed/cachecontrol/compat.pyi +++ b/mypy-stubs/cachecontrol/compat.pyi @@ -4,4 +4,4 @@ from typing import Any -text_type = ... # type: Any +str = ... # type: Any diff --git a/mypy-stubs/cachecontrol/controller.pyi b/mypy-stubs/cachecontrol/controller.pyi new file mode 100644 index 0000000..e8a06aa --- /dev/null +++ b/mypy-stubs/cachecontrol/controller.pyi @@ -0,0 +1,18 @@ +from typing import Collection + +from _typeshed import Incomplete + +from .cache import BaseCache + +class CacheController: + cache: BaseCache + cache_etags: bool + serializer: Incomplete + cacheable_status_codes: Collection[int] | None = None + def __init__( + self, + cache: BaseCache | None = None, + cache_etags: bool = True, + serializer: Incomplete | None = None, + status_codes: Collection[int] | None = None, + ) -> None: ... diff --git a/mypy-stubs/cachecontrol/wrapper.pyi b/mypy-stubs/cachecontrol/wrapper.pyi new file mode 100644 index 0000000..6244687 --- /dev/null +++ b/mypy-stubs/cachecontrol/wrapper.pyi @@ -0,0 +1,18 @@ +from typing import Collection, Type + +from _typeshed import Incomplete +from requests import Session + +from .cache import BaseCache +from .controller import CacheController + +def CacheControl( + sess: Session, + cache: BaseCache | None = None, + cache_etags: bool = True, + serializer: Incomplete | None = None, + heuristic: Incomplete | None = None, + controller_class: Type[CacheController] | None = None, + adapter_class: Incomplete | None = None, + cacheable_methods: Collection[str] | None = None, +) -> Session: ... diff --git a/mypy-stubs/junit_xml.pyi b/mypy-stubs/junit_xml.pyi new file mode 100644 index 0000000..e305ce4 --- /dev/null +++ b/mypy-stubs/junit_xml.pyi @@ -0,0 +1,93 @@ +# Stubs for junit_xml (Python 3.5) +# +# NOTE: This dynamically typed stub was automatically generated by stubgen. + +from typing import IO, Any, List, Optional + +unichr = chr + +class TestSuite: + name: Any = ... + test_cases: Any = ... + timestamp: Any = ... + hostname: Any = ... + id: Any = ... + package: Any = ... + file: Any = ... + log: Any = ... + url: Any = ... + stdout: Any = ... + stderr: Any = ... + properties: Any = ... + def __init__( + self, + name: str, + test_cases: Optional[Any] = ..., + hostname: Optional[Any] = ..., + id: Optional[Any] = ..., + package: Optional[Any] = ..., + timestamp: Optional[Any] = ..., + properties: Optional[Any] = ..., + file: Optional[Any] = ..., + log: Optional[Any] = ..., + url: Optional[Any] = ..., + stdout: Optional[Any] = ..., + stderr: Optional[Any] = ..., + ) -> None: ... + +class TestCase: + name: Any = ... + assertions: Any = ... + elapsed_sec: Any = ... + timestamp: Any = ... + classname: Any = ... + status: Any = ... + category: Any = ... + file: Any = ... + line: Any = ... + log: Any = ... + url: Any = ... + stdout: Any = ... + stderr: Any = ... + is_enabled: bool = ... + error_message: Any = ... + error_output: Any = ... + error_type: Any = ... + failure_message: Any = ... + failure_output: Any = ... + failure_type: Any = ... + skipped_message: Any = ... + skipped_output: Any = ... + def __init__( + self, + name: str, + classname: Optional[Any] = ..., + elapsed_sec: Optional[Any] = ..., + stdout: Optional[Any] = ..., + stderr: Optional[Any] = ..., + assertions: Optional[Any] = ..., + timestamp: Optional[Any] = ..., + status: Optional[Any] = ..., + category: Optional[Any] = ..., + file: Optional[Any] = ..., + line: Optional[Any] = ..., + log: Optional[Any] = ..., + group: Optional[Any] = ..., + url: Optional[Any] = ..., + ) -> None: ... + def add_failure_info( + self, + message: Optional[Any] = ..., + output: Optional[Any] = ..., + failure_type: Optional[Any] = ..., + ) -> None: ... + def add_skipped_info( + self, message: Optional[Any] = ..., output: Optional[Any] = ... + ) -> None: ... + +def to_xml_report_file( + file_descriptor: IO[Any], + test_suites: List[TestSuite], + prettyprint: bool = True, + encoding: Optional[str] = None, +) -> None: ... diff --git a/mypy-stubs/rdflib/__init__.pyi b/mypy-stubs/rdflib/__init__.pyi new file mode 100644 index 0000000..03d8e90 --- /dev/null +++ b/mypy-stubs/rdflib/__init__.pyi @@ -0,0 +1,32 @@ +from rdflib.graph import ConjunctiveGraph as ConjunctiveGraph +from rdflib.graph import Graph as Graph +from rdflib.namespace import CSVW as CSVW +from rdflib.namespace import DC as DC +from rdflib.namespace import DCAT as DCAT +from rdflib.namespace import DCTERMS as DCTERMS +from rdflib.namespace import DOAP as DOAP +from rdflib.namespace import FOAF as FOAF +from rdflib.namespace import ODRL2 as ODRL2 +from rdflib.namespace import ORG as ORG +from rdflib.namespace import OWL as OWL +from rdflib.namespace import PROF as PROF +from rdflib.namespace import PROV as PROV +from rdflib.namespace import QB as QB +from rdflib.namespace import RDF as RDF +from rdflib.namespace import RDFS as RDFS +from rdflib.namespace import SDO as SDO +from rdflib.namespace import SH as SH +from rdflib.namespace import SKOS as SKOS +from rdflib.namespace import SOSA as SOSA +from rdflib.namespace import SSN as SSN +from rdflib.namespace import TIME as TIME +from rdflib.namespace import VOID as VOID +from rdflib.namespace import XMLNS as XMLNS +from rdflib.namespace import XSD as XSD +from rdflib.namespace import Namespace as Namespace +from rdflib.term import BNode as BNode +from rdflib.term import Literal as Literal +from rdflib.term import URIRef as URIRef +from rdflib.term import Variable as Variable + +__version__: str diff --git a/mypy-stubs/rdflib/collection.pyi b/mypy-stubs/rdflib/collection.pyi new file mode 100644 index 0000000..0bee984 --- /dev/null +++ b/mypy-stubs/rdflib/collection.pyi @@ -0,0 +1,19 @@ +from typing import Any, Iterator + +from rdflib.graph import Graph +from rdflib.term import Node + +class Collection: + graph: Graph + uri: Node + def __init__(self, graph: Graph, uri: Node, seq: Any = ...) -> None: ... + def n3(self) -> str: ... + def __len__(self) -> int: ... + def index(self, item: Any) -> int: ... + def __getitem__(self, key: str) -> Any: ... + def __setitem__(self, key: str, value: Any) -> None: ... + def __delitem__(self, key: str) -> None: ... + def __iter__(self) -> Iterator[Any]: ... + def append(self, item: Any) -> Collection: ... + def __iadd__(self, other: Any) -> Collection: ... + def clear(self) -> Collection: ... diff --git a/mypy-stubs/rdflib/compare.pyi b/mypy-stubs/rdflib/compare.pyi new file mode 100644 index 0000000..6451292 --- /dev/null +++ b/mypy-stubs/rdflib/compare.pyi @@ -0,0 +1,10 @@ +from typing import Dict, Union + +from rdflib.graph import ConjunctiveGraph, Graph + +Stats = Dict[str, Union[int, str]] + +class IsomorphicGraph(ConjunctiveGraph): + pass + +def to_isomorphic(graph: Graph = ...) -> IsomorphicGraph: ... diff --git a/mypy-stubs/rdflib/graph.pyi b/mypy-stubs/rdflib/graph.pyi new file mode 100644 index 0000000..23c2e6e --- /dev/null +++ b/mypy-stubs/rdflib/graph.pyi @@ -0,0 +1,252 @@ +import pathlib +from typing import ( + IO, + Any, + Iterable, + Iterator, + List, + Optional, + Set, + Tuple, + Union, + overload, +) + +from rdflib import query +from rdflib.collection import Collection +from rdflib.paths import Path +from rdflib.resource import Resource +from rdflib.term import BNode, Identifier, Node + +class Graph(Node): + base: Any = ... + context_aware: bool = ... + formula_aware: bool = ... + default_union: bool = ... + def __init__( + self, + store: str = ..., + identifier: Optional[Any] = ..., + namespace_manager: Optional[Any] = ..., + base: Optional[Any] = ..., + ) -> None: ... + store: Any = ... + identifier: Any = ... + namespace_manager: Any = ... + def toPython(self) -> str: ... + def destroy(self, configuration: Any) -> None: ... + def commit(self) -> None: ... + def rollback(self) -> None: ... + def open(self, configuration: Any, create: bool = ...) -> Any: ... + def close(self, commit_pending_transaction: bool = ...) -> None: ... + def add(self, triple: Any) -> None: ... + def addN(self, quads: Any) -> None: ... + def remove(self, triple: Any) -> None: ... + def triples( + self, + triple: Tuple[ + Optional[Union[str, Identifier]], + Optional[Union[str, Identifier]], + Optional[Identifier], + ], + ) -> Iterator[Tuple[Identifier, Identifier, Identifier]]: ... + def __getitem__( + self, item: slice | Path | Node + ) -> Iterator[ + Tuple[Identifier, Identifier, Identifier] | Tuple[Identifier, identifier] | Node + ]: ... + def __contains__(self, triple: Any) -> bool: ... + def __add__(self, other: Any) -> Graph: ... + def set(self, triple: Any) -> None: ... + def subjects( + self, predicate: Optional[Any] = ..., object: Optional[Any] = ... + ) -> Iterable[Node]: ... + def predicates( + self, subject: Optional[Any] = ..., object: Optional[Any] = ... + ) -> Iterable[Node]: ... + def objects( + self, subject: Optional[Any] = ..., predicate: Optional[Any] = ... + ) -> Iterable[Identifier]: ... + def subject_predicates(self, object: Optional[Any] = ...) -> None: ... + def subject_objects(self, predicate: Optional[Any] = ...) -> None: ... + def predicate_objects(self, subject: Optional[Any] = ...) -> None: ... + def triples_choices(self, triple: Any, context: Optional[Any] = ...) -> None: ... + def value( + self, + subject: Optional[Any] = ..., + predicate: Any = ..., + object: Optional[Any] = ..., + default: Optional[Any] = ..., + any: bool = ..., + ) -> Any: ... + def label(self, subject: Any, default: str = ...) -> Any: ... + def preferredLabel( + self, + subject: Any, + lang: Optional[Any] = ..., + default: Optional[Any] = ..., + labelProperties: Any = ..., + ) -> List[Tuple[Any, Any]]: ... + def comment(self, subject: Any, default: str = ...) -> Any: ... + def items(self, list: Any) -> Iterator[Any]: ... + def transitiveClosure( + self, func: Any, arg: Any, seen: Optional[Any] = ... + ) -> Iterator[Any]: ... + def transitive_objects( + self, subject: Any, property: Any, remember: Optional[Any] = ... + ) -> Iterator[Any]: ... + def transitive_subjects( + self, predicate: Any, object: Any, remember: Optional[Any] = ... + ) -> Iterator[Any]: ... + def seq(self, subject: Any) -> Seq | None: ... + def qname(self, uri: Any) -> Any: ... + def compute_qname(self, uri: Any, generate: bool = ...) -> Any: ... + def bind( + self, prefix: Any, namespace: Any, override: bool = ..., replace: bool = ... + ) -> Any: ... + def namespaces(self) -> Iterator[Tuple[Any, Any]]: ... + def absolutize(self, uri: Any, defrag: int = ...) -> Any: ... + + # no destination and non-None positional encoding + @overload + def serialize( + self, + destination: None, + format: str, + base: Optional[str], + encoding: str, + **args: Any, + ) -> bytes: ... + + # no destination and non-None keyword encoding + @overload + def serialize( + self, + destination: None = ..., + format: str = ..., + base: Optional[str] = ..., + *, + encoding: str, + **args: Any, + ) -> bytes: ... + + # no destination and None encoding + @overload + def serialize( + self, + destination: None = ..., + format: str = ..., + base: Optional[str] = ..., + encoding: None = ..., + **args: Any, + ) -> str: ... + + # non-None destination + @overload + def serialize( + self, + destination: Union[str, pathlib.PurePath, IO[bytes]], + format: str = ..., + base: Optional[str] = ..., + encoding: Optional[str] = ..., + **args: Any, + ) -> "Graph": ... + + # fallback + @overload + def serialize( + self, + destination: Optional[Union[str, pathlib.PurePath, IO[bytes]]] = ..., + format: str = ..., + base: Optional[str] = ..., + encoding: Optional[str] = ..., + **args: Any, + ) -> Union[bytes, str, "Graph"]: ... + def parse( + self, + source: Optional[Any] = ..., + publicID: Optional[Any] = ..., + format: Optional[str] = ..., + location: Optional[Any] = ..., + file: Optional[Any] = ..., + data: Optional[Any] = ..., + **args: Any, + ) -> "Graph": ... + def load( + self, source: Any, publicID: Optional[Any] = ..., format: str = ... + ) -> "Graph": ... + def query( + self, + query_object: Any, + processor: str = ..., + result: str = ..., + initNs: Optional[Any] = ..., + initBindings: Optional[Any] = ..., + use_store_provided: bool = ..., + **kwargs: Any, + ) -> query.Result: ... + def update( + self, + update_object: Any, + processor: str = ..., + initNs: Optional[Any] = ..., + initBindings: Optional[Any] = ..., + use_store_provided: bool = ..., + **kwargs: Any, + ) -> Any: ... + def n3(self) -> str: ... + def isomorphic(self, other: Any) -> bool: ... + def connected(self) -> bool: ... + def all_nodes(self) -> Set[Any]: ... + def collection(self, identifier: Any) -> Collection: ... + def resource(self, identifier: Any) -> Resource: ... + def skolemize( + self, + new_graph: Optional[Any] = ..., + bnode: Optional[Any] = ..., + authority: Optional[Any] = ..., + basepath: Optional[Any] = ..., + ) -> Graph: ... + def de_skolemize( + self, new_graph: Optional[Any] = ..., uriref: Optional[Any] = ... + ) -> Graph: ... + +class ConjunctiveGraph(Graph): + context_aware: bool = ... + default_union: bool = ... + default_context: Any = ... + def __init__( + self, + store: str = ..., + identifier: Optional[Any] = ..., + default_graph_base: Optional[Any] = ..., + ) -> None: ... + def add(self, triple_or_quad: Any) -> None: ... + def addN(self, quads: Any) -> None: ... + def remove(self, triple_or_quad: Any) -> None: ... + # def triples(self, triple_or_quad: Tuple[Optional[Union[str, BNode]], Optional[Union[str, BNode]], Optional[BNode]], context: Tuple[Optional[Union[str, BNode]], Optional[Union[str, BNode]], Optional[BNode]]) -> Iterator[Tuple[Identifier, Identifier, Identifier]]: ... + def quads(self, triple_or_quad: Optional[Any] = ...) -> None: ... + def triples_choices(self, triple: Any, context: Optional[Any] = ...) -> None: ... + def contexts(self, triple: Optional[Any] = ...) -> None: ... + def get_context( + self, + identifier: Node | str | None, + quoted: bool = ..., + base: Optional[str] = ..., + ) -> Graph: ... + def remove_context(self, context: Any) -> None: ... + def context_id(self, uri: Any, context_id: Optional[Any] = ...) -> Any: ... + def parse( + self, + source: Optional[Any] = ..., + publicID: Optional[Any] = ..., + format: Optional[str] = ..., + location: Optional[Any] = ..., + file: Optional[Any] = ..., + data: Optional[Any] = ..., + **args: Any, + ) -> Graph: ... + +class Seq: + def __init__(self, graph: Graph, subject: Any) -> None: ... + def toPython(self) -> Seq: ... diff --git a/mypy-stubs/rdflib/namespace/_CSVW.pyi b/mypy-stubs/rdflib/namespace/_CSVW.pyi new file mode 100644 index 0000000..aa1b137 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_CSVW.pyi @@ -0,0 +1,88 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class CSVW(DefinedNamespace): + aboutUrl: URIRef + base: URIRef + column: URIRef + columnReference: URIRef + commentPrefix: URIRef + datatype: URIRef + decimalChar: URIRef + default: URIRef + delimiter: URIRef + describes: URIRef + dialect: URIRef + doubleQuote: URIRef + encoding: URIRef + foreignKey: URIRef + format: URIRef + groupChar: URIRef + header: URIRef + headerRowCount: URIRef + lang: URIRef + length: URIRef + lineTerminators: URIRef + maxExclusive: URIRef + maxInclusive: URIRef + maxLength: URIRef + minExclusive: URIRef + minInclusive: URIRef + minLength: URIRef + name: URIRef + note: URIRef + null: URIRef + ordered: URIRef + pattern: URIRef + primaryKey: URIRef + propertyUrl: URIRef + quoteChar: URIRef + reference: URIRef + referencedRow: URIRef + required: URIRef + resource: URIRef + row: URIRef + rowTitle: URIRef + rownum: URIRef + schemaReference: URIRef + scriptFormat: URIRef + separator: URIRef + skipBlankRows: URIRef + skipColumns: URIRef + skipInitialSpace: URIRef + skipRows: URIRef + source: URIRef + suppressOutput: URIRef + table: URIRef + tableDirection: URIRef + tableSchema: URIRef + targetFormat: URIRef + textDirection: URIRef + title: URIRef + transformations: URIRef + trim: URIRef + url: URIRef + valueUrl: URIRef + virtual: URIRef + Cell: URIRef + Column: URIRef + Datatype: URIRef + Dialect: URIRef + Direction: URIRef + ForeignKey: URIRef + NumericFormat: URIRef + Row: URIRef + Schema: URIRef + Table: URIRef + TableGroup: URIRef + TableReference: URIRef + Transformation: URIRef + JSON: URIRef + uriTemplate: URIRef + auto: URIRef + inherit: URIRef + ltr: URIRef + rtl: URIRef + csvEncodedTabularData: URIRef + tabularMetadata: URIRef diff --git a/mypy-stubs/rdflib/namespace/_DC.pyi b/mypy-stubs/rdflib/namespace/_DC.pyi new file mode 100644 index 0000000..25d75e8 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_DC.pyi @@ -0,0 +1,20 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class DC(DefinedNamespace): + contributor: URIRef + coverage: URIRef + creator: URIRef + date: URIRef + description: URIRef + format: URIRef + identifier: URIRef + language: URIRef + publisher: URIRef + relation: URIRef + rights: URIRef + source: URIRef + subject: URIRef + title: URIRef + type: URIRef diff --git a/mypy-stubs/rdflib/namespace/_DCAT.pyi b/mypy-stubs/rdflib/namespace/_DCAT.pyi new file mode 100644 index 0000000..c920687 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_DCAT.pyi @@ -0,0 +1,41 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class DCAT(DefinedNamespace): + accessURL: URIRef + bbox: URIRef + byteSize: URIRef + centroid: URIRef + compressFormat: URIRef + contactPoint: URIRef + dataset: URIRef + distribution: URIRef + downloadURL: URIRef + endDate: URIRef + keyword: URIRef + landingPage: URIRef + mediaType: URIRef + packageFormat: URIRef + record: URIRef + startDate: URIRef + theme: URIRef + themeTaxonomy: URIRef + Catalog: URIRef + CatalogRecord: URIRef + Dataset: URIRef + Distribution: URIRef + DataService: URIRef + Relationship: URIRef + Resource: URIRef + Role: URIRef + spatialResolutionInMeters: URIRef + temporalResolution: URIRef + accessService: URIRef + catalog: URIRef + endpointDescription: URIRef + endpointURL: URIRef + hadRole: URIRef + qualifiedRelation: URIRef + servesDataset: URIRef + service: URIRef diff --git a/mypy-stubs/rdflib/namespace/_DCTERMS.pyi b/mypy-stubs/rdflib/namespace/_DCTERMS.pyi new file mode 100644 index 0000000..3c5d77f --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_DCTERMS.pyi @@ -0,0 +1,101 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class DCTERMS(DefinedNamespace): + DCMIType: URIRef + DDC: URIRef + IMT: URIRef + LCC: URIRef + LCSH: URIRef + MESH: URIRef + NLM: URIRef + TGN: URIRef + UDC: URIRef + abstract: URIRef + accessRights: URIRef + accrualMethod: URIRef + accrualPeriodicity: URIRef + accrualPolicy: URIRef + alternative: URIRef + audience: URIRef + available: URIRef + bibliographicCitation: URIRef + conformsTo: URIRef + contributor: URIRef + coverage: URIRef + created: URIRef + creator: URIRef + date: URIRef + dateAccepted: URIRef + dateCopyrighted: URIRef + dateSubmitted: URIRef + description: URIRef + educationLevel: URIRef + extent: URIRef + format: URIRef + hasFormat: URIRef + hasPart: URIRef + hasVersion: URIRef + identifier: URIRef + instructionalMethod: URIRef + isFormatOf: URIRef + isPartOf: URIRef + isReferencedBy: URIRef + isReplacedBy: URIRef + isRequiredBy: URIRef + isVersionOf: URIRef + issued: URIRef + language: URIRef + license: URIRef + mediator: URIRef + medium: URIRef + modified: URIRef + provenance: URIRef + publisher: URIRef + references: URIRef + relation: URIRef + replaces: URIRef + requires: URIRef + rights: URIRef + rightsHolder: URIRef + source: URIRef + spatial: URIRef + subject: URIRef + tableOfContents: URIRef + temporal: URIRef + title: URIRef + type: URIRef + valid: URIRef + Agent: URIRef + AgentClass: URIRef + BibliographicResource: URIRef + FileFormat: URIRef + Frequency: URIRef + Jurisdiction: URIRef + LicenseDocument: URIRef + LinguisticSystem: URIRef + Location: URIRef + LocationPeriodOrJurisdiction: URIRef + MediaType: URIRef + MediaTypeOrExtent: URIRef + MethodOfAccrual: URIRef + MethodOfInstruction: URIRef + PeriodOfTime: URIRef + PhysicalMedium: URIRef + PhysicalResource: URIRef + Policy: URIRef + ProvenanceStatement: URIRef + RightsStatement: URIRef + SizeOrDuration: URIRef + Standard: URIRef + Box: URIRef + ISO3166: URIRef + Period: URIRef + Point: URIRef + RFC1766: URIRef + RFC3066: URIRef + RFC4646: URIRef + RFC5646: URIRef + URI: URIRef + W3CDTF: URIRef diff --git a/mypy-stubs/rdflib/namespace/_DOAP.pyi b/mypy-stubs/rdflib/namespace/_DOAP.pyi new file mode 100644 index 0000000..846f8be --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_DOAP.pyi @@ -0,0 +1,47 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class DOAP(DefinedNamespace): + audience: URIRef + blog: URIRef + browse: URIRef + category: URIRef + created: URIRef + description: URIRef + developer: URIRef + documenter: URIRef + helper: URIRef + implements: URIRef + language: URIRef + license: URIRef + location: URIRef + maintainer: URIRef + module: URIRef + name: URIRef + os: URIRef + platform: URIRef + release: URIRef + repository: URIRef + repositoryOf: URIRef + revision: URIRef + screenshots: URIRef + shortdesc: URIRef + tester: URIRef + translator: URIRef + vendor: URIRef + wiki: URIRef + ArchRepository: URIRef + BKRepository: URIRef + BazaarBranch: URIRef + CVSRepository: URIRef + DarcsRepository: URIRef + GitBranch: URIRef + GitRepository: URIRef + HgRepository: URIRef + Project: URIRef + Repository: URIRef + SVNRepository: URIRef + Specification: URIRef + Version: URIRef + homepage: URIRef diff --git a/mypy-stubs/rdflib/namespace/_FOAF.pyi b/mypy-stubs/rdflib/namespace/_FOAF.pyi new file mode 100644 index 0000000..50923a1 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_FOAF.pyi @@ -0,0 +1,80 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class FOAF(DefinedNamespace): + account: URIRef + accountName: URIRef + accountServiceHomepage: URIRef + age: URIRef + based_near: URIRef + birthday: URIRef + currentProject: URIRef + depiction: URIRef + depicts: URIRef + dnaChecksum: URIRef + familyName: URIRef + family_name: URIRef + firstName: URIRef + focus: URIRef + fundedBy: URIRef + geekcode: URIRef + gender: URIRef + givenName: URIRef + givenname: URIRef + holdsAccount: URIRef + img: URIRef + interest: URIRef + knows: URIRef + lastName: URIRef + made: URIRef + maker: URIRef + member: URIRef + membershipClass: URIRef + myersBriggs: URIRef + name: URIRef + nick: URIRef + page: URIRef + pastProject: URIRef + phone: URIRef + plan: URIRef + primaryTopic: URIRef + publications: URIRef + schoolHomepage: URIRef + sha1: URIRef + skypeID: URIRef + status: URIRef + surname: URIRef + theme: URIRef + thumbnail: URIRef + tipjar: URIRef + title: URIRef + topic: URIRef + topic_interest: URIRef + workInfoHomepage: URIRef + workplaceHomepage: URIRef + Agent: URIRef + Document: URIRef + Group: URIRef + Image: URIRef + LabelProperty: URIRef + OnlineAccount: URIRef + OnlineChatAccount: URIRef + OnlineEcommerceAccount: URIRef + OnlineGamingAccount: URIRef + Organization: URIRef + Person: URIRef + PersonalProfileDocument: URIRef + Project: URIRef + aimChatID: URIRef + homepage: URIRef + icqChatID: URIRef + isPrimaryTopicOf: URIRef + jabberID: URIRef + logo: URIRef + mbox: URIRef + mbox_sha1sum: URIRef + msnChatID: URIRef + openid: URIRef + weblog: URIRef + yahooChatID: URIRef diff --git a/mypy-stubs/rdflib/namespace/_ODRL2.pyi b/mypy-stubs/rdflib/namespace/_ODRL2.pyi new file mode 100644 index 0000000..37e7556 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_ODRL2.pyi @@ -0,0 +1,209 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class ODRL2(DefinedNamespace): + action: URIRef + andSequence: URIRef + assignee: URIRef + assigneeOf: URIRef + assigner: URIRef + assignerOf: URIRef + attributedParty: URIRef + attributingParty: URIRef + compensatedParty: URIRef + compensatingParty: URIRef + conflict: URIRef + consentedParty: URIRef + consentingParty: URIRef + consequence: URIRef + constraint: URIRef + contractedParty: URIRef + contractingParty: URIRef + dataType: URIRef + duty: URIRef + failure: URIRef + function: URIRef + hasPolicy: URIRef + implies: URIRef + includedIn: URIRef + informedParty: URIRef + informingParty: URIRef + inheritAllowed: URIRef + inheritFrom: URIRef + inheritRelation: URIRef + leftOperand: URIRef + obligation: URIRef + operand: URIRef + operator: URIRef + output: URIRef + partOf: URIRef + payeeParty: URIRef + permission: URIRef + profile: URIRef + prohibition: URIRef + proximity: URIRef + refinement: URIRef + relation: URIRef + remedy: URIRef + rightOperand: URIRef + rightOperandReference: URIRef + scope: URIRef + source: URIRef + status: URIRef + target: URIRef + timedCount: URIRef + trackedParty: URIRef + trackingParty: URIRef + uid: URIRef + undefined: URIRef + unit: URIRef + xone: URIRef + All: URIRef + All2ndConnections: URIRef + AllConnections: URIRef + AllGroups: URIRef + Group: URIRef + Individual: URIRef + absolutePosition: URIRef + absoluteSize: URIRef + absoluteSpatialPosition: URIRef + absoluteTemporalPosition: URIRef + count: URIRef + dateTime: URIRef + delayPeriod: URIRef + deliveryChannel: URIRef + device: URIRef + elapsedTime: URIRef + eq: URIRef + event: URIRef + fileFormat: URIRef + gt: URIRef + gteq: URIRef + hasPart: URIRef + ignore: URIRef + industry: URIRef + invalid: URIRef + isA: URIRef + isAllOf: URIRef + isAnyOf: URIRef + isNoneOf: URIRef + isPartOf: URIRef + language: URIRef + lt: URIRef + lteq: URIRef + media: URIRef + meteredTime: URIRef + neq: URIRef + payAmount: URIRef + percentage: URIRef + perm: URIRef + policyUsage: URIRef + product: URIRef + prohibit: URIRef + purpose: URIRef + recipient: URIRef + relativePosition: URIRef + relativeSize: URIRef + relativeSpatialPosition: URIRef + relativeTemporalPosition: URIRef + resolution: URIRef + spatial: URIRef + spatialCoordinates: URIRef + support: URIRef + system: URIRef + systemDevice: URIRef + timeInterval: URIRef + unitOfCount: URIRef + version: URIRef + virtualLocation: URIRef + Action: URIRef + Agreement: URIRef + Assertion: URIRef + Asset: URIRef + AssetCollection: URIRef + AssetScope: URIRef + ConflictTerm: URIRef + Constraint: URIRef + Duty: URIRef + LeftOperand: URIRef + LogicalConstraint: URIRef + Offer: URIRef + Operator: URIRef + Party: URIRef + PartyCollection: URIRef + PartyScope: URIRef + Permission: URIRef + Policy: URIRef + Privacy: URIRef + Prohibition: URIRef + Request: URIRef + RightOperand: URIRef + Rule: URIRef + Set: URIRef + Ticket: URIRef + UndefinedTerm: URIRef + acceptTracking: URIRef + adHocShare: URIRef + aggregate: URIRef + annotate: URIRef + anonymize: URIRef + append: URIRef + appendTo: URIRef + archive: URIRef + attachPolicy: URIRef + attachSource: URIRef + attribute: URIRef + commercialize: URIRef + compensate: URIRef + concurrentUse: URIRef + copy: URIRef + core: URIRef + delete: URIRef + derive: URIRef + digitize: URIRef + display: URIRef + distribute: URIRef + ensureExclusivity: URIRef + execute: URIRef + export: URIRef + extract: URIRef + extractChar: URIRef + extractPage: URIRef + extractWord: URIRef + give: URIRef + grantUse: URIRef + include: URIRef + index: URIRef + inform: URIRef + install: URIRef + lease: URIRef + lend: URIRef + license: URIRef + modify: URIRef + move: URIRef + nextPolicy: URIRef + obtainConsent: URIRef + pay: URIRef + play: URIRef + present: URIRef + preview: URIRef + print: URIRef + read: URIRef + reproduce: URIRef + reviewPolicy: URIRef + secondaryUse: URIRef + sell: URIRef + share: URIRef + shareAlike: URIRef + stream: URIRef + synchronize: URIRef + textToSpeech: URIRef + transfer: URIRef + transform: URIRef + translate: URIRef + uninstall: URIRef + use: URIRef + watermark: URIRef + write: URIRef + writeTo: URIRef diff --git a/mypy-stubs/rdflib/namespace/_ORG.pyi b/mypy-stubs/rdflib/namespace/_ORG.pyi new file mode 100644 index 0000000..e7cd07f --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_ORG.pyi @@ -0,0 +1,50 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class ORG(DefinedNamespace): + basedAt: URIRef + changedBy: URIRef + classification: URIRef + hasMember: URIRef + hasMembership: URIRef + hasPost: URIRef + hasPrimarySite: URIRef + hasRegisteredSite: URIRef + hasSite: URIRef + hasSubOrganization: URIRef + hasUnit: URIRef + headOf: URIRef + heldBy: URIRef + holds: URIRef + identifier: URIRef + linkedTo: URIRef + location: URIRef + member: URIRef + memberDuring: URIRef + memberOf: URIRef + organization: URIRef + originalOrganization: URIRef + postIn: URIRef + purpose: URIRef + remuneration: URIRef + reportsTo: URIRef + resultedFrom: URIRef + resultingOrganization: URIRef + role: URIRef + roleProperty: URIRef + siteAddress: URIRef + siteOf: URIRef + subOrganizationOf: URIRef + transitiveSubOrganizationOf: URIRef + unitOf: URIRef + ChangeEvent: URIRef + FormalOrganization: URIRef + Membership: URIRef + Organization: URIRef + OrganizationalCollaboration: URIRef + OrganizationalUnit: URIRef + Post: URIRef + Role: URIRef + Site: URIRef + Head: URIRef diff --git a/mypy-stubs/rdflib/namespace/_OWL.pyi b/mypy-stubs/rdflib/namespace/_OWL.pyi new file mode 100644 index 0000000..e789663 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_OWL.pyi @@ -0,0 +1,82 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class OWL(DefinedNamespace): + allValuesFrom: URIRef + annotatedProperty: URIRef + annotatedSource: URIRef + annotatedTarget: URIRef + assertionProperty: URIRef + cardinality: URIRef + complementOf: URIRef + datatypeComplementOf: URIRef + differentFrom: URIRef + disjointUnionOf: URIRef + disjointWith: URIRef + distinctMembers: URIRef + equivalentClass: URIRef + equivalentProperty: URIRef + hasKey: URIRef + hasSelf: URIRef + hasValue: URIRef + intersectionOf: URIRef + inverseOf: URIRef + maxCardinality: URIRef + maxQualifiedCardinality: URIRef + members: URIRef + minCardinality: URIRef + minQualifiedCardinality: URIRef + onClass: URIRef + onDataRange: URIRef + onDatatype: URIRef + onProperties: URIRef + onProperty: URIRef + oneOf: URIRef + propertyChainAxiom: URIRef + propertyDisjointWith: URIRef + qualifiedCardinality: URIRef + sameAs: URIRef + someValuesFrom: URIRef + sourceIndividual: URIRef + targetIndividual: URIRef + targetValue: URIRef + unionOf: URIRef + withRestrictions: URIRef + AllDifferent: URIRef + AllDisjointClasses: URIRef + AllDisjointProperties: URIRef + Annotation: URIRef + AnnotationProperty: URIRef + AsymmetricProperty: URIRef + Axiom: URIRef + Class: URIRef + DataRange: URIRef + DatatypeProperty: URIRef + DeprecatedClass: URIRef + DeprecatedProperty: URIRef + FunctionalProperty: URIRef + InverseFunctionalProperty: URIRef + IrreflexiveProperty: URIRef + NamedIndividual: URIRef + NegativePropertyAssertion: URIRef + ObjectProperty: URIRef + Ontology: URIRef + OntologyProperty: URIRef + ReflexiveProperty: URIRef + Restriction: URIRef + SymmetricProperty: URIRef + TransitiveProperty: URIRef + backwardCompatibleWith: URIRef + deprecated: URIRef + incompatibleWith: URIRef + priorVersion: URIRef + versionInfo: URIRef + Nothing: URIRef + Thing: URIRef + bottomDataProperty: URIRef + topDataProperty: URIRef + bottomObjectProperty: URIRef + topObjectProperty: URIRef + imports: URIRef + versionIRI: URIRef diff --git a/mypy-stubs/rdflib/namespace/_PROF.pyi b/mypy-stubs/rdflib/namespace/_PROF.pyi new file mode 100644 index 0000000..69df238 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_PROF.pyi @@ -0,0 +1,15 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class PROF(DefinedNamespace): + Profile: URIRef + ResourceDescriptor: URIRef + ResourceRole: URIRef + hasToken: URIRef + hasArtifact: URIRef + hasResource: URIRef + hasRole: URIRef + isInheritedFrom: URIRef + isProfileOf: URIRef + isTransitiveProfileOf: URIRef diff --git a/mypy-stubs/rdflib/namespace/_PROV.pyi b/mypy-stubs/rdflib/namespace/_PROV.pyi new file mode 100644 index 0000000..bfe1ad9 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_PROV.pyi @@ -0,0 +1,175 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class PROV(DefinedNamespace): + activityOfInfluence: URIRef + agentOfInfluence: URIRef + contributed: URIRef + ended: URIRef + entityOfInfluence: URIRef + generalizationOf: URIRef + generatedAsDerivation: URIRef + hadDelegate: URIRef + hadDerivation: URIRef + hadInfluence: URIRef + hadRevision: URIRef + informed: URIRef + locationOf: URIRef + qualifiedAssociationOf: URIRef + qualifiedAttributionOf: URIRef + qualifiedCommunicationOf: URIRef + qualifiedDelegationOf: URIRef + qualifiedDerivationOf: URIRef + qualifiedEndOf: URIRef + qualifiedGenerationOf: URIRef + qualifiedInfluenceOf: URIRef + qualifiedInvalidationOf: URIRef + qualifiedQuotationOf: URIRef + qualifiedSourceOf: URIRef + qualifiedStartOf: URIRef + qualifiedUsingActivity: URIRef + quotedAs: URIRef + revisedEntity: URIRef + started: URIRef + wasActivityOfInfluence: URIRef + wasAssociateFor: URIRef + wasMemberOf: URIRef + wasPlanOf: URIRef + wasPrimarySourceOf: URIRef + wasRoleIn: URIRef + wasUsedBy: URIRef + wasUsedInDerivation: URIRef + aq: URIRef + category: URIRef + component: URIRef + constraints: URIRef + definition: URIRef + dm: URIRef + editorialNote: URIRef + editorsDefinition: URIRef + inverse: URIRef + n: URIRef + order: URIRef + qualifiedForm: URIRef + sharesDefinitionWith: URIRef + specializationOf: URIRef + todo: URIRef + unqualifiedForm: URIRef + wasRevisionOf: URIRef + Accept: URIRef + Activity: URIRef + ActivityInfluence: URIRef + Agent: URIRef + AgentInfluence: URIRef + Association: URIRef + Attribution: URIRef + Bundle: URIRef + Collection: URIRef + Communication: URIRef + Contribute: URIRef + Contributor: URIRef + Copyright: URIRef + Create: URIRef + Creator: URIRef + Delegation: URIRef + Derivation: URIRef + Dictionary: URIRef + DirectQueryService: URIRef + EmptyDictionary: URIRef + End: URIRef + Entity: URIRef + EntityInfluence: URIRef + Generation: URIRef + Influence: URIRef + Insertion: URIRef + InstantaneousEvent: URIRef + Invalidation: URIRef + KeyEntityPair: URIRef + Location: URIRef + Modify: URIRef + Organization: URIRef + Person: URIRef + Plan: URIRef + PrimarySource: URIRef + Publish: URIRef + Publisher: URIRef + Quotation: URIRef + Removal: URIRef + Replace: URIRef + Revision: URIRef + RightsAssignment: URIRef + RightsHolder: URIRef + Role: URIRef + ServiceDescription: URIRef + SoftwareAgent: URIRef + Start: URIRef + Submit: URIRef + Usage: URIRef + atTime: URIRef + endedAtTime: URIRef + generatedAtTime: URIRef + invalidatedAtTime: URIRef + provenanceUriTemplate: URIRef + removedKey: URIRef + startedAtTime: URIRef + value: URIRef + pairEntity: URIRef + pairKey: URIRef + EmptyCollection: URIRef + actedOnBehalfOf: URIRef + activity: URIRef + agent: URIRef + alternateOf: URIRef + asInBundle: URIRef + atLocation: URIRef + derivedByInsertionFrom: URIRef + derivedByRemovalFrom: URIRef + describesService: URIRef + dictionary: URIRef + entity: URIRef + generated: URIRef + hadActivity: URIRef + hadDictionaryMember: URIRef + hadGeneration: URIRef + hadMember: URIRef + hadPlan: URIRef + hadPrimarySource: URIRef + hadRole: URIRef + hadUsage: URIRef + has_anchor: URIRef + has_provenance: URIRef + has_query_service: URIRef + influenced: URIRef + influencer: URIRef + insertedKeyEntityPair: URIRef + invalidated: URIRef + mentionOf: URIRef + pingback: URIRef + qualifiedAssociation: URIRef + qualifiedAttribution: URIRef + qualifiedCommunication: URIRef + qualifiedDelegation: URIRef + qualifiedDerivation: URIRef + qualifiedEnd: URIRef + qualifiedGeneration: URIRef + qualifiedInfluence: URIRef + qualifiedInsertion: URIRef + qualifiedInvalidation: URIRef + qualifiedPrimarySource: URIRef + qualifiedQuotation: URIRef + qualifiedRemoval: URIRef + qualifiedRevision: URIRef + qualifiedStart: URIRef + qualifiedUsage: URIRef + used: URIRef + wasAssociatedWith: URIRef + wasAttributedTo: URIRef + wasDerivedFrom: URIRef + wasEndedBy: URIRef + wasGeneratedBy: URIRef + wasInfluencedBy: URIRef + wasInformedBy: URIRef + wasInvalidatedBy: URIRef + wasQuotedFrom: URIRef + wasStartedBy: URIRef diff --git a/mypy-stubs/rdflib/namespace/_QB.pyi b/mypy-stubs/rdflib/namespace/_QB.pyi new file mode 100644 index 0000000..4b90460 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_QB.pyi @@ -0,0 +1,41 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class QB(DefinedNamespace): + attribute: URIRef + codeList: URIRef + component: URIRef + componentAttachment: URIRef + componentProperty: URIRef + componentRequired: URIRef + concept: URIRef + dataSet: URIRef + dimension: URIRef + hierarchyRoot: URIRef + measure: URIRef + measureDimension: URIRef + measureType: URIRef + observation: URIRef + observationGroup: URIRef + order: URIRef + parentChildProperty: URIRef + slice: URIRef + sliceKey: URIRef + sliceStructure: URIRef + structure: URIRef + Attachable: URIRef + AttributeProperty: URIRef + CodedProperty: URIRef + ComponentProperty: URIRef + ComponentSet: URIRef + ComponentSpecification: URIRef + DataSet: URIRef + DataStructureDefinition: URIRef + DimensionProperty: URIRef + HierarchicalCodeList: URIRef + MeasureProperty: URIRef + Observation: URIRef + ObservationGroup: URIRef + Slice: URIRef + SliceKey: URIRef diff --git a/mypy-stubs/rdflib/namespace/_RDF.pyi b/mypy-stubs/rdflib/namespace/_RDF.pyi new file mode 100644 index 0000000..e613019 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_RDF.pyi @@ -0,0 +1,27 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class RDF(DefinedNamespace): + nil: URIRef + direction: URIRef + first: URIRef + language: URIRef + object: URIRef + predicate: URIRef + rest: URIRef + subject: URIRef + type: URIRef + value: URIRef + Alt: URIRef + Bag: URIRef + CompoundLiteral: URIRef + List: URIRef + Property: URIRef + Seq: URIRef + Statement: URIRef + HTML: URIRef + JSON: URIRef + PlainLiteral: URIRef + XMLLiteral: URIRef + langString: URIRef diff --git a/mypy-stubs/rdflib/namespace/_RDFS.pyi b/mypy-stubs/rdflib/namespace/_RDFS.pyi new file mode 100644 index 0000000..e28d084 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_RDFS.pyi @@ -0,0 +1,20 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class RDFS(DefinedNamespace): + comment: URIRef + domain: URIRef + isDefinedBy: URIRef + label: URIRef + member: URIRef + range: URIRef + seeAlso: URIRef + subClassOf: URIRef + subPropertyOf: URIRef + Class: URIRef + Container: URIRef + ContainerMembershipProperty: URIRef + Datatype: URIRef + Literal: URIRef + Resource: URIRef diff --git a/mypy-stubs/rdflib/namespace/_SDO.pyi b/mypy-stubs/rdflib/namespace/_SDO.pyi new file mode 100644 index 0000000..b974b4d --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_SDO.pyi @@ -0,0 +1,1645 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class SDO(DefinedNamespace): + ActiveActionStatus: URIRef + CompletedActionStatus: URIRef + FailedActionStatus: URIRef + PotentialActionStatus: URIRef + Researcher: URIRef + GroupBoardingPolicy: URIRef + ZoneBoardingPolicy: URIRef + AudiobookFormat: URIRef + EBook: URIRef + Hardcover: URIRef + Paperback: URIRef + HearingImpairedSupported: URIRef + TollFree: URIRef + Friday: URIRef + Monday: URIRef + PublicHolidays: URIRef + Saturday: URIRef + Sunday: URIRef + Thursday: URIRef + Tuesday: URIRef + Wednesday: URIRef + OnSitePickup: URIRef + CommentPermission: URIRef + ReadPermission: URIRef + WritePermission: URIRef + AllWheelDriveConfiguration: URIRef + FourWheelDriveConfiguration: URIRef + FrontWheelDriveConfiguration: URIRef + RearWheelDriveConfiguration: URIRef + EventCancelled: URIRef + EventMovedOnline: URIRef + EventPostponed: URIRef + EventRescheduled: URIRef + EventScheduled: URIRef + CoOp: URIRef + MultiPlayer: URIRef + SinglePlayer: URIRef + OfflinePermanently: URIRef + OfflineTemporarily: URIRef + Online: URIRef + OnlineFull: URIRef + Female: URIRef + Male: URIRef + Discontinued: URIRef + InStock: URIRef + InStoreOnly: URIRef + LimitedAvailability: URIRef + OnlineOnly: URIRef + OutOfStock: URIRef + PreOrder: URIRef + PreSale: URIRef + SoldOut: URIRef + ItemListOrderAscending: URIRef + ItemListOrderDescending: URIRef + ItemListUnordered: URIRef + ParkingMap: URIRef + SeatingMap: URIRef + TransitMap: URIRef + VenueMap: URIRef + CompilationAlbum: URIRef + DJMixAlbum: URIRef + DemoAlbum: URIRef + LiveAlbum: URIRef + MixtapeAlbum: URIRef + RemixAlbum: URIRef + SoundtrackAlbum: URIRef + SpokenWordAlbum: URIRef + StudioAlbum: URIRef + AlbumRelease: URIRef + BroadcastRelease: URIRef + EPRelease: URIRef + SingleRelease: URIRef + CDFormat: URIRef + CassetteFormat: URIRef + DVDFormat: URIRef + DigitalAudioTapeFormat: URIRef + DigitalFormat: URIRef + LaserDiscFormat: URIRef + VinylFormat: URIRef + DamagedCondition: URIRef + NewCondition: URIRef + RefurbishedCondition: URIRef + UsedCondition: URIRef + OrderCancelled: URIRef + OrderDelivered: URIRef + OrderInTransit: URIRef + OrderPaymentDue: URIRef + OrderPickupAvailable: URIRef + OrderProblem: URIRef + OrderProcessing: URIRef + OrderReturned: URIRef + PaymentAutomaticallyApplied: URIRef + PaymentComplete: URIRef + PaymentDeclined: URIRef + PaymentDue: URIRef + PaymentPastDue: URIRef + ReservationCancelled: URIRef + ReservationConfirmed: URIRef + ReservationHold: URIRef + ReservationPending: URIRef + DiabeticDiet: URIRef + GlutenFreeDiet: URIRef + HalalDiet: URIRef + HinduDiet: URIRef + KosherDiet: URIRef + LowCalorieDiet: URIRef + LowFatDiet: URIRef + LowLactoseDiet: URIRef + LowSaltDiet: URIRef + VeganDiet: URIRef + VegetarianDiet: URIRef + RsvpResponseMaybe: URIRef + RsvpResponseNo: URIRef + RsvpResponseYes: URIRef + LeftHandDriving: URIRef + RightHandDriving: URIRef + about: URIRef + acceptedAnswer: URIRef + acceptedOffer: URIRef + acceptedPaymentMethod: URIRef + acceptsReservations: URIRef + accessCode: URIRef + accessMode: URIRef + accessModeSufficient: URIRef + accessibilityAPI: URIRef + accessibilityControl: URIRef + accessibilityFeature: URIRef + accessibilityHazard: URIRef + accessibilitySummary: URIRef + accountId: URIRef + accountablePerson: URIRef + acquiredFrom: URIRef + actionAccessibilityRequirement: URIRef + actionApplication: URIRef + actionOption: URIRef + actionPlatform: URIRef + actionStatus: URIRef + actor: URIRef + actors: URIRef + addOn: URIRef + additionalName: URIRef + additionalNumberOfGuests: URIRef + additionalProperty: URIRef + additionalType: URIRef + address: URIRef + addressCountry: URIRef + addressLocality: URIRef + addressRegion: URIRef + advanceBookingRequirement: URIRef + affiliation: URIRef + afterMedia: URIRef + agent: URIRef + aggregateRating: URIRef + aircraft: URIRef + album: URIRef + albumProductionType: URIRef + albumRelease: URIRef + albumReleaseType: URIRef + albums: URIRef + alignmentType: URIRef + alternateName: URIRef + alternativeHeadline: URIRef + alumni: URIRef + alumniOf: URIRef + amenityFeature: URIRef + amount: URIRef + amountOfThisGood: URIRef + annualPercentageRate: URIRef + answerCount: URIRef + application: URIRef + applicationCategory: URIRef + applicationSubCategory: URIRef + applicationSuite: URIRef + appliesToDeliveryMethod: URIRef + appliesToPaymentMethod: URIRef + area: URIRef + areaServed: URIRef + arrivalAirport: URIRef + arrivalBusStop: URIRef + arrivalGate: URIRef + arrivalPlatform: URIRef + arrivalStation: URIRef + arrivalTerminal: URIRef + arrivalTime: URIRef + artEdition: URIRef + artMedium: URIRef + artform: URIRef + articleBody: URIRef + articleSection: URIRef + artworkSurface: URIRef + assembly: URIRef + assemblyVersion: URIRef + associatedArticle: URIRef + associatedMedia: URIRef + athlete: URIRef + attendee: URIRef + attendees: URIRef + audience: URIRef + audienceType: URIRef + audio: URIRef + authenticator: URIRef + author: URIRef + availability: URIRef + availabilityEnds: URIRef + availabilityStarts: URIRef + availableAtOrFrom: URIRef + availableChannel: URIRef + availableDeliveryMethod: URIRef + availableFrom: URIRef + availableLanguage: URIRef + availableOnDevice: URIRef + availableThrough: URIRef + award: URIRef + awards: URIRef + awayTeam: URIRef + baseSalary: URIRef + bccRecipient: URIRef + bed: URIRef + beforeMedia: URIRef + benefits: URIRef + bestRating: URIRef + billingAddress: URIRef + billingIncrement: URIRef + billingPeriod: URIRef + birthDate: URIRef + birthPlace: URIRef + bitrate: URIRef + blogPost: URIRef + blogPosts: URIRef + boardingGroup: URIRef + boardingPolicy: URIRef + bookEdition: URIRef + bookFormat: URIRef + bookingAgent: URIRef + bookingTime: URIRef + borrower: URIRef + box: URIRef + branchCode: URIRef + branchOf: URIRef + brand: URIRef + breadcrumb: URIRef + broadcastAffiliateOf: URIRef + broadcastChannelId: URIRef + broadcastDisplayName: URIRef + broadcastFrequency: URIRef + broadcastFrequencyValue: URIRef + broadcastOfEvent: URIRef + broadcastServiceTier: URIRef + broadcastTimezone: URIRef + broadcaster: URIRef + broker: URIRef + browserRequirements: URIRef + busName: URIRef + busNumber: URIRef + businessFunction: URIRef + buyer: URIRef + byArtist: URIRef + calories: URIRef + candidate: URIRef + caption: URIRef + carbohydrateContent: URIRef + cargoVolume: URIRef + carrier: URIRef + carrierRequirements: URIRef + catalog: URIRef + catalogNumber: URIRef + category: URIRef + ccRecipient: URIRef + character: URIRef + characterAttribute: URIRef + characterName: URIRef + cheatCode: URIRef + checkinTime: URIRef + checkoutTime: URIRef + childMaxAge: URIRef + childMinAge: URIRef + children: URIRef + cholesterolContent: URIRef + circle: URIRef + citation: URIRef + claimReviewed: URIRef + clipNumber: URIRef + closes: URIRef + coach: URIRef + codeRepository: URIRef + codeSampleType: URIRef + colleague: URIRef + colleagues: URIRef + collection: URIRef + color: URIRef + comment: URIRef + commentCount: URIRef + commentText: URIRef + commentTime: URIRef + competitor: URIRef + composer: URIRef + confirmationNumber: URIRef + contactOption: URIRef + contactPoint: URIRef + contactPoints: URIRef + contactType: URIRef + containedIn: URIRef + containedInPlace: URIRef + containsPlace: URIRef + containsSeason: URIRef + contentLocation: URIRef + contentRating: URIRef + contentSize: URIRef + contentType: URIRef + contentUrl: URIRef + contributor: URIRef + cookTime: URIRef + cookingMethod: URIRef + copyrightHolder: URIRef + copyrightYear: URIRef + countriesNotSupported: URIRef + countriesSupported: URIRef + countryOfOrigin: URIRef + course: URIRef + courseCode: URIRef + courseMode: URIRef + coursePrerequisites: URIRef + coverageEndTime: URIRef + coverageStartTime: URIRef + creator: URIRef + creditedTo: URIRef + cssSelector: URIRef + currenciesAccepted: URIRef + currency: URIRef + customer: URIRef + dataFeedElement: URIRef + dataset: URIRef + datasetTimeInterval: URIRef + dateCreated: URIRef + dateDeleted: URIRef + dateIssued: URIRef + dateModified: URIRef + datePosted: URIRef + datePublished: URIRef + dateRead: URIRef + dateReceived: URIRef + dateSent: URIRef + dateVehicleFirstRegistered: URIRef + dateline: URIRef + dayOfWeek: URIRef + deathDate: URIRef + deathPlace: URIRef + defaultValue: URIRef + deliveryAddress: URIRef + deliveryLeadTime: URIRef + deliveryMethod: URIRef + deliveryStatus: URIRef + department: URIRef + departureAirport: URIRef + departureBusStop: URIRef + departureGate: URIRef + departurePlatform: URIRef + departureStation: URIRef + departureTerminal: URIRef + departureTime: URIRef + dependencies: URIRef + depth: URIRef + description: URIRef + device: URIRef + director: URIRef + directors: URIRef + disambiguatingDescription: URIRef + discount: URIRef + discountCode: URIRef + discountCurrency: URIRef + discusses: URIRef + discussionUrl: URIRef + dissolutionDate: URIRef + distance: URIRef + distribution: URIRef + doorTime: URIRef + downloadUrl: URIRef + downvoteCount: URIRef + driveWheelConfiguration: URIRef + dropoffLocation: URIRef + dropoffTime: URIRef + duns: URIRef + duration: URIRef + durationOfWarranty: URIRef + duringMedia: URIRef + editor: URIRef + educationalAlignment: URIRef + educationalCredentialAwarded: URIRef + educationalFramework: URIRef + educationalRole: URIRef + educationalUse: URIRef + elevation: URIRef + eligibleCustomerType: URIRef + eligibleDuration: URIRef + eligibleQuantity: URIRef + eligibleRegion: URIRef + eligibleTransactionVolume: URIRef + email: URIRef + embedUrl: URIRef + employee: URIRef + employees: URIRef + employmentType: URIRef + encodesCreativeWork: URIRef + encoding: URIRef + encodingFormat: URIRef + encodingType: URIRef + encodings: URIRef + endDate: URIRef + endTime: URIRef + endorsee: URIRef + entertainmentBusiness: URIRef + episode: URIRef + episodeNumber: URIRef + episodes: URIRef + equal: URIRef + error: URIRef + estimatedCost: URIRef + estimatedFlightDuration: URIRef + estimatedSalary: URIRef + event: URIRef + eventStatus: URIRef + events: URIRef + exampleOfWork: URIRef + executableLibraryName: URIRef + exerciseCourse: URIRef + exifData: URIRef + expectedArrivalFrom: URIRef + expectedArrivalUntil: URIRef + expectsAcceptanceOf: URIRef + experienceRequirements: URIRef + expires: URIRef + familyName: URIRef + fatContent: URIRef + faxNumber: URIRef + featureList: URIRef + feesAndCommissionsSpecification: URIRef + fiberContent: URIRef + fileFormat: URIRef + fileSize: URIRef + firstPerformance: URIRef + flightDistance: URIRef + flightNumber: URIRef + floorSize: URIRef + followee: URIRef + follows: URIRef + foodEstablishment: URIRef + foodEvent: URIRef + founder: URIRef + founders: URIRef + foundingDate: URIRef + foundingLocation: URIRef + free: URIRef + fromLocation: URIRef + fuelConsumption: URIRef + fuelEfficiency: URIRef + fuelType: URIRef + funder: URIRef + game: URIRef + gameItem: URIRef + gameLocation: URIRef + gamePlatform: URIRef + gameServer: URIRef + gameTip: URIRef + genre: URIRef + geo: URIRef + geoContains: URIRef + geoCoveredBy: URIRef + geoCovers: URIRef + geoCrosses: URIRef + geoDisjoint: URIRef + geoEquals: URIRef + geoIntersects: URIRef + geoMidpoint: URIRef + geoOverlaps: URIRef + geoRadius: URIRef + geoTouches: URIRef + geoWithin: URIRef + geographicArea: URIRef + givenName: URIRef + globalLocationNumber: URIRef + grantee: URIRef + greater: URIRef + greaterOrEqual: URIRef + gtin12: URIRef + gtin13: URIRef + gtin14: URIRef + gtin8: URIRef + hasBroadcastChannel: URIRef + hasCourseInstance: URIRef + hasDeliveryMethod: URIRef + hasDigitalDocumentPermission: URIRef + hasMap: URIRef + hasMenu: URIRef + hasMenuItem: URIRef + hasMenuSection: URIRef + hasOccupation: URIRef + hasOfferCatalog: URIRef + hasPOS: URIRef + hasPart: URIRef + headline: URIRef + height: URIRef + highPrice: URIRef + hiringOrganization: URIRef + homeLocation: URIRef + homeTeam: URIRef + honorificPrefix: URIRef + honorificSuffix: URIRef + hostingOrganization: URIRef + hoursAvailable: URIRef + httpMethod: URIRef + iataCode: URIRef + icaoCode: URIRef + identifier: URIRef + illustrator: URIRef + image: URIRef + inAlbum: URIRef + inBroadcastLineup: URIRef + inLanguage: URIRef + inPlaylist: URIRef + incentiveCompensation: URIRef + incentives: URIRef + includedComposition: URIRef + includedDataCatalog: URIRef + includedInDataCatalog: URIRef + includesObject: URIRef + industry: URIRef + ingredients: URIRef + installUrl: URIRef + instructor: URIRef + instrument: URIRef + interactionCount: URIRef + interactionService: URIRef + interactionStatistic: URIRef + interactionType: URIRef + interactivityType: URIRef + interestRate: URIRef + inventoryLevel: URIRef + isAccessibleForFree: URIRef + isAccessoryOrSparePartFor: URIRef + isBasedOn: URIRef + isBasedOnUrl: URIRef + isConsumableFor: URIRef + isFamilyFriendly: URIRef + isGift: URIRef + isLiveBroadcast: URIRef + isPartOf: URIRef + isRelatedTo: URIRef + isSimilarTo: URIRef + isVariantOf: URIRef + isbn: URIRef + isicV4: URIRef + isrcCode: URIRef + issn: URIRef + issueNumber: URIRef + issuedBy: URIRef + issuedThrough: URIRef + iswcCode: URIRef + item: URIRef + itemCondition: URIRef + itemListElement: URIRef + itemListOrder: URIRef + itemOffered: URIRef + itemReviewed: URIRef + itemShipped: URIRef + jobBenefits: URIRef + jobLocation: URIRef + keywords: URIRef + knownVehicleDamages: URIRef + knows: URIRef + landlord: URIRef + language: URIRef + lastReviewed: URIRef + latitude: URIRef + learningResourceType: URIRef + legalName: URIRef + leiCode: URIRef + lender: URIRef + lesser: URIRef + lesserOrEqual: URIRef + license: URIRef + line: URIRef + liveBlogUpdate: URIRef + loanTerm: URIRef + location: URIRef + locationCreated: URIRef + lodgingUnitDescription: URIRef + lodgingUnitType: URIRef + logo: URIRef + longitude: URIRef + loser: URIRef + lowPrice: URIRef + lyricist: URIRef + lyrics: URIRef + mainContentOfPage: URIRef + mainEntity: URIRef + mainEntityOfPage: URIRef + makesOffer: URIRef + manufacturer: URIRef + map: URIRef + mapType: URIRef + maps: URIRef + material: URIRef + maxPrice: URIRef + maxValue: URIRef + maximumAttendeeCapacity: URIRef + mealService: URIRef + median: URIRef + member: URIRef + memberOf: URIRef + members: URIRef + membershipNumber: URIRef + memoryRequirements: URIRef + mentions: URIRef + menu: URIRef + menuAddOn: URIRef + merchant: URIRef + messageAttachment: URIRef + mileageFromOdometer: URIRef + minPrice: URIRef + minValue: URIRef + minimumPaymentDue: URIRef + model: URIRef + modifiedTime: URIRef + mpn: URIRef + multipleValues: URIRef + musicArrangement: URIRef + musicBy: URIRef + musicCompositionForm: URIRef + musicGroupMember: URIRef + musicReleaseFormat: URIRef + musicalKey: URIRef + naics: URIRef + name: URIRef + namedPosition: URIRef + nationality: URIRef + netWorth: URIRef + nextItem: URIRef + nonEqual: URIRef + numAdults: URIRef + numChildren: URIRef + numTracks: URIRef + numberOfAirbags: URIRef + numberOfAxles: URIRef + numberOfBeds: URIRef + numberOfDoors: URIRef + numberOfEmployees: URIRef + numberOfEpisodes: URIRef + numberOfForwardGears: URIRef + numberOfItems: URIRef + numberOfPages: URIRef + numberOfPlayers: URIRef + numberOfPreviousOwners: URIRef + numberOfRooms: URIRef + numberOfSeasons: URIRef + numberedPosition: URIRef + nutrition: URIRef + object: URIRef + occupancy: URIRef + occupationLocation: URIRef + offerCount: URIRef + offeredBy: URIRef + offers: URIRef + openingHours: URIRef + openingHoursSpecification: URIRef + opens: URIRef + operatingSystem: URIRef + opponent: URIRef + option: URIRef + orderDate: URIRef + orderDelivery: URIRef + orderItemNumber: URIRef + orderItemStatus: URIRef + orderNumber: URIRef + orderQuantity: URIRef + orderStatus: URIRef + orderedItem: URIRef + organizer: URIRef + originAddress: URIRef + ownedFrom: URIRef + ownedThrough: URIRef + owns: URIRef + pageEnd: URIRef + pageStart: URIRef + pagination: URIRef + parent: URIRef + parentItem: URIRef + parentOrganization: URIRef + parentService: URIRef + parents: URIRef + partOfEpisode: URIRef + partOfInvoice: URIRef + partOfOrder: URIRef + partOfSeason: URIRef + partOfSeries: URIRef + partOfTVSeries: URIRef + participant: URIRef + partySize: URIRef + passengerPriorityStatus: URIRef + passengerSequenceNumber: URIRef + paymentAccepted: URIRef + paymentDue: URIRef + paymentDueDate: URIRef + paymentMethod: URIRef + paymentMethodId: URIRef + paymentStatus: URIRef + paymentUrl: URIRef + percentile10: URIRef + percentile25: URIRef + percentile75: URIRef + percentile90: URIRef + performTime: URIRef + performer: URIRef + performerIn: URIRef + performers: URIRef + permissionType: URIRef + permissions: URIRef + permitAudience: URIRef + permittedUsage: URIRef + petsAllowed: URIRef + photo: URIRef + photos: URIRef + pickupLocation: URIRef + pickupTime: URIRef + playMode: URIRef + playerType: URIRef + playersOnline: URIRef + polygon: URIRef + position: URIRef + postOfficeBoxNumber: URIRef + postalCode: URIRef + potentialAction: URIRef + predecessorOf: URIRef + prepTime: URIRef + previousItem: URIRef + previousStartDate: URIRef + price: URIRef + priceComponent: URIRef + priceCurrency: URIRef + priceRange: URIRef + priceSpecification: URIRef + priceType: URIRef + priceValidUntil: URIRef + primaryImageOfPage: URIRef + printColumn: URIRef + printEdition: URIRef + printPage: URIRef + printSection: URIRef + processingTime: URIRef + processorRequirements: URIRef + producer: URIRef + produces: URIRef + productID: URIRef + productSupported: URIRef + productionCompany: URIRef + productionDate: URIRef + proficiencyLevel: URIRef + programMembershipUsed: URIRef + programName: URIRef + programmingLanguage: URIRef + programmingModel: URIRef + propertyID: URIRef + proteinContent: URIRef + provider: URIRef + providerMobility: URIRef + providesBroadcastService: URIRef + providesService: URIRef + publicAccess: URIRef + publication: URIRef + publishedOn: URIRef + publisher: URIRef + publishingPrinciples: URIRef + purchaseDate: URIRef + query: URIRef + quest: URIRef + question: URIRef + ratingCount: URIRef + ratingValue: URIRef + readonlyValue: URIRef + realEstateAgent: URIRef + recipe: URIRef + recipeCategory: URIRef + recipeCuisine: URIRef + recipeIngredient: URIRef + recipeInstructions: URIRef + recipeYield: URIRef + recipient: URIRef + recordLabel: URIRef + recordedAs: URIRef + recordedAt: URIRef + recordedIn: URIRef + recordingOf: URIRef + referenceQuantity: URIRef + referencesOrder: URIRef + regionsAllowed: URIRef + relatedLink: URIRef + relatedTo: URIRef + releaseDate: URIRef + releaseNotes: URIRef + releaseOf: URIRef + releasedEvent: URIRef + relevantOccupation: URIRef + remainingAttendeeCapacity: URIRef + replacee: URIRef + replacer: URIRef + replyToUrl: URIRef + reportNumber: URIRef + representativeOfPage: URIRef + requiredCollateral: URIRef + requiredGender: URIRef + requiredMaxAge: URIRef + requiredMinAge: URIRef + requiredQuantity: URIRef + requirements: URIRef + requiresSubscription: URIRef + reservationFor: URIRef + reservationId: URIRef + reservationStatus: URIRef + reservedTicket: URIRef + responsibilities: URIRef + result: URIRef + resultComment: URIRef + resultReview: URIRef + review: URIRef + reviewAspect: URIRef + reviewBody: URIRef + reviewCount: URIRef + reviewRating: URIRef + reviewedBy: URIRef + reviews: URIRef + roleName: URIRef + rsvpResponse: URIRef + runtime: URIRef + runtimePlatform: URIRef + salaryCurrency: URIRef + sameAs: URIRef + sampleType: URIRef + saturatedFatContent: URIRef + scheduledPaymentDate: URIRef + scheduledTime: URIRef + schemaVersion: URIRef + screenCount: URIRef + screenshot: URIRef + season: URIRef + seasonNumber: URIRef + seasons: URIRef + seatNumber: URIRef + seatRow: URIRef + seatSection: URIRef + seatingType: URIRef + securityScreening: URIRef + seeks: URIRef + seller: URIRef + sender: URIRef + serialNumber: URIRef + serverStatus: URIRef + servesCuisine: URIRef + serviceArea: URIRef + serviceAudience: URIRef + serviceLocation: URIRef + serviceOperator: URIRef + serviceOutput: URIRef + servicePhone: URIRef + servicePostalAddress: URIRef + serviceSmsNumber: URIRef + serviceType: URIRef + serviceUrl: URIRef + servingSize: URIRef + sharedContent: URIRef + sibling: URIRef + siblings: URIRef + significantLink: URIRef + significantLinks: URIRef + skills: URIRef + sku: URIRef + slogan: URIRef + smokingAllowed: URIRef + sodiumContent: URIRef + softwareAddOn: URIRef + softwareHelp: URIRef + softwareRequirements: URIRef + softwareVersion: URIRef + sourceOrganization: URIRef + spatial: URIRef + spatialCoverage: URIRef + speakable: URIRef + specialCommitments: URIRef + specialOpeningHoursSpecification: URIRef + specialty: URIRef + sponsor: URIRef + sportsActivityLocation: URIRef + sportsEvent: URIRef + sportsTeam: URIRef + spouse: URIRef + starRating: URIRef + startDate: URIRef + startTime: URIRef + steeringPosition: URIRef + step: URIRef + stepValue: URIRef + steps: URIRef + storageRequirements: URIRef + streetAddress: URIRef + subEvent: URIRef + subEvents: URIRef + subOrganization: URIRef + subReservation: URIRef + subjectOf: URIRef + successorOf: URIRef + sugarContent: URIRef + suggestedAnswer: URIRef + suggestedGender: URIRef + suggestedMaxAge: URIRef + suggestedMinAge: URIRef + suitableForDiet: URIRef + superEvent: URIRef + supply: URIRef + supportingData: URIRef + surface: URIRef + target: URIRef + targetCollection: URIRef + targetDescription: URIRef + targetName: URIRef + targetPlatform: URIRef + targetProduct: URIRef + targetUrl: URIRef + taxID: URIRef + telephone: URIRef + temporal: URIRef + temporalCoverage: URIRef + text: URIRef + thumbnail: URIRef + thumbnailUrl: URIRef + tickerSymbol: URIRef + ticketNumber: URIRef + ticketToken: URIRef + ticketedSeat: URIRef + timeRequired: URIRef + title: URIRef + toLocation: URIRef + toRecipient: URIRef + tool: URIRef + totalPaymentDue: URIRef + totalPrice: URIRef + totalTime: URIRef + touristType: URIRef + track: URIRef + trackingNumber: URIRef + trackingUrl: URIRef + tracks: URIRef + trailer: URIRef + trainName: URIRef + trainNumber: URIRef + transFatContent: URIRef + transcript: URIRef + translator: URIRef + typeOfBed: URIRef + typeOfGood: URIRef + typicalAgeRange: URIRef + underName: URIRef + unitCode: URIRef + unitText: URIRef + unsaturatedFatContent: URIRef + uploadDate: URIRef + upvoteCount: URIRef + url: URIRef + urlTemplate: URIRef + userInteractionCount: URIRef + validFor: URIRef + validFrom: URIRef + validIn: URIRef + validThrough: URIRef + validUntil: URIRef + value: URIRef + valueAddedTaxIncluded: URIRef + valueMaxLength: URIRef + valueMinLength: URIRef + valueName: URIRef + valuePattern: URIRef + valueReference: URIRef + valueRequired: URIRef + vatID: URIRef + vehicleConfiguration: URIRef + vehicleEngine: URIRef + vehicleIdentificationNumber: URIRef + vehicleInteriorColor: URIRef + vehicleInteriorType: URIRef + vehicleModelDate: URIRef + vehicleSeatingCapacity: URIRef + vehicleTransmission: URIRef + vendor: URIRef + version: URIRef + video: URIRef + videoFormat: URIRef + videoFrameSize: URIRef + videoQuality: URIRef + volumeNumber: URIRef + warranty: URIRef + warrantyPromise: URIRef + warrantyScope: URIRef + webCheckinTime: URIRef + weight: URIRef + width: URIRef + winner: URIRef + wordCount: URIRef + workExample: URIRef + workFeatured: URIRef + workHours: URIRef + workLocation: URIRef + workPerformed: URIRef + workPresented: URIRef + worksFor: URIRef + worstRating: URIRef + xpath: URIRef + yearlyRevenue: URIRef + yearsInOperation: URIRef + AMRadioChannel: URIRef + APIReference: URIRef + AboutPage: URIRef + AcceptAction: URIRef + Accommodation: URIRef + AccountingService: URIRef + AchieveAction: URIRef + Action: URIRef + ActionAccessSpecification: URIRef + ActionStatusType: URIRef + ActivateAction: URIRef + AddAction: URIRef + AdministrativeArea: URIRef + AdultEntertainment: URIRef + AggregateOffer: URIRef + AggregateRating: URIRef + AgreeAction: URIRef + Airline: URIRef + Airport: URIRef + AlignmentObject: URIRef + AllocateAction: URIRef + AmusementPark: URIRef + AnimalShelter: URIRef + Answer: URIRef + Apartment: URIRef + ApartmentComplex: URIRef + AppendAction: URIRef + ApplyAction: URIRef + Aquarium: URIRef + ArriveAction: URIRef + ArtGallery: URIRef + Article: URIRef + AskAction: URIRef + AssessAction: URIRef + AssignAction: URIRef + Attorney: URIRef + Audience: URIRef + AudioObject: URIRef + AuthorizeAction: URIRef + AutoBodyShop: URIRef + AutoDealer: URIRef + AutoPartsStore: URIRef + AutoRental: URIRef + AutoRepair: URIRef + AutoWash: URIRef + AutomatedTeller: URIRef + AutomotiveBusiness: URIRef + Bakery: URIRef + BankAccount: URIRef + BankOrCreditUnion: URIRef + BarOrPub: URIRef + Barcode: URIRef + Beach: URIRef + BeautySalon: URIRef + BedAndBreakfast: URIRef + BedDetails: URIRef + BedType: URIRef + BefriendAction: URIRef + BikeStore: URIRef + Blog: URIRef + BlogPosting: URIRef + BoardingPolicyType: URIRef + BodyOfWater: URIRef + Book: URIRef + BookFormatType: URIRef + BookSeries: URIRef + BookStore: URIRef + BookmarkAction: URIRef + Boolean: URIRef + BorrowAction: URIRef + BowlingAlley: URIRef + Brand: URIRef + BreadcrumbList: URIRef + Brewery: URIRef + Bridge: URIRef + BroadcastChannel: URIRef + BroadcastEvent: URIRef + BroadcastFrequencySpecification: URIRef + BroadcastService: URIRef + BuddhistTemple: URIRef + BusReservation: URIRef + BusStation: URIRef + BusStop: URIRef + BusTrip: URIRef + BusinessAudience: URIRef + BusinessEntityType: URIRef + BusinessEvent: URIRef + BusinessFunction: URIRef + BuyAction: URIRef + CableOrSatelliteService: URIRef + CafeOrCoffeeShop: URIRef + Campground: URIRef + CampingPitch: URIRef + Canal: URIRef + CancelAction: URIRef + Car: URIRef + Casino: URIRef + CatholicChurch: URIRef + Cemetery: URIRef + CheckAction: URIRef + CheckInAction: URIRef + CheckOutAction: URIRef + CheckoutPage: URIRef + ChildCare: URIRef + ChildrensEvent: URIRef + ChooseAction: URIRef + Church: URIRef + City: URIRef + CityHall: URIRef + CivicStructure: URIRef + ClaimReview: URIRef + Clip: URIRef + ClothingStore: URIRef + Code: URIRef + CollectionPage: URIRef + CollegeOrUniversity: URIRef + ComedyClub: URIRef + ComedyEvent: URIRef + Comment: URIRef + CommentAction: URIRef + CommunicateAction: URIRef + CompoundPriceSpecification: URIRef + ComputerLanguage: URIRef + ComputerStore: URIRef + ConfirmAction: URIRef + ConsumeAction: URIRef + ContactPage: URIRef + ContactPoint: URIRef + ContactPointOption: URIRef + Continent: URIRef + ControlAction: URIRef + ConvenienceStore: URIRef + Conversation: URIRef + CookAction: URIRef + Corporation: URIRef + Country: URIRef + Course: URIRef + CourseInstance: URIRef + Courthouse: URIRef + CreateAction: URIRef + CreativeWork: URIRef + CreativeWorkSeason: URIRef + CreativeWorkSeries: URIRef + CreditCard: URIRef + Crematorium: URIRef + CurrencyConversionService: URIRef + DanceEvent: URIRef + DanceGroup: URIRef + DataCatalog: URIRef + DataDownload: URIRef + DataFeed: URIRef + DataFeedItem: URIRef + DataType: URIRef + Dataset: URIRef + Date: URIRef + DateTime: URIRef + DatedMoneySpecification: URIRef + DayOfWeek: URIRef + DaySpa: URIRef + DeactivateAction: URIRef + DefenceEstablishment: URIRef + DeleteAction: URIRef + DeliveryChargeSpecification: URIRef + DeliveryEvent: URIRef + DeliveryMethod: URIRef + Demand: URIRef + Dentist: URIRef + DepartAction: URIRef + DepartmentStore: URIRef + DepositAccount: URIRef + DigitalDocument: URIRef + DigitalDocumentPermission: URIRef + DigitalDocumentPermissionType: URIRef + DisagreeAction: URIRef + DiscoverAction: URIRef + DiscussionForumPosting: URIRef + DislikeAction: URIRef + Distance: URIRef + Distillery: URIRef + DonateAction: URIRef + DownloadAction: URIRef + DrawAction: URIRef + DrinkAction: URIRef + DriveWheelConfigurationValue: URIRef + DryCleaningOrLaundry: URIRef + Duration: URIRef + EatAction: URIRef + EducationEvent: URIRef + EducationalAudience: URIRef + EducationalOrganization: URIRef + Electrician: URIRef + ElectronicsStore: URIRef + ElementarySchool: URIRef + EmailMessage: URIRef + Embassy: URIRef + EmergencyService: URIRef + EmployeeRole: URIRef + EmployerAggregateRating: URIRef + EmploymentAgency: URIRef + EndorseAction: URIRef + EndorsementRating: URIRef + Energy: URIRef + EngineSpecification: URIRef + EntertainmentBusiness: URIRef + EntryPoint: URIRef + Enumeration: URIRef + Episode: URIRef + Event: URIRef + EventReservation: URIRef + EventStatusType: URIRef + EventVenue: URIRef + ExerciseAction: URIRef + ExerciseGym: URIRef + ExhibitionEvent: URIRef + FAQPage: URIRef + FMRadioChannel: URIRef + FastFoodRestaurant: URIRef + Festival: URIRef + FilmAction: URIRef + FinancialProduct: URIRef + FinancialService: URIRef + FindAction: URIRef + FireStation: URIRef + Flight: URIRef + FlightReservation: URIRef + Float: URIRef + Florist: URIRef + FollowAction: URIRef + FoodEstablishment: URIRef + FoodEstablishmentReservation: URIRef + FoodEvent: URIRef + FoodService: URIRef + FurnitureStore: URIRef + Game: URIRef + GamePlayMode: URIRef + GameServer: URIRef + GameServerStatus: URIRef + GardenStore: URIRef + GasStation: URIRef + GatedResidenceCommunity: URIRef + GenderType: URIRef + GeneralContractor: URIRef + GeoCircle: URIRef + GeoCoordinates: URIRef + GeoShape: URIRef + GiveAction: URIRef + GolfCourse: URIRef + GovernmentBuilding: URIRef + GovernmentOffice: URIRef + GovernmentOrganization: URIRef + GovernmentPermit: URIRef + GovernmentService: URIRef + GroceryStore: URIRef + HVACBusiness: URIRef + HairSalon: URIRef + HardwareStore: URIRef + HealthAndBeautyBusiness: URIRef + HealthClub: URIRef + HighSchool: URIRef + HinduTemple: URIRef + HobbyShop: URIRef + HomeAndConstructionBusiness: URIRef + HomeGoodsStore: URIRef + Hospital: URIRef + Hostel: URIRef + Hotel: URIRef + HotelRoom: URIRef + House: URIRef + HousePainter: URIRef + HowTo: URIRef + HowToDirection: URIRef + HowToItem: URIRef + HowToSection: URIRef + HowToStep: URIRef + HowToSupply: URIRef + HowToTip: URIRef + HowToTool: URIRef + IceCreamShop: URIRef + IgnoreAction: URIRef + ImageGallery: URIRef + ImageObject: URIRef + IndividualProduct: URIRef + InformAction: URIRef + InsertAction: URIRef + InstallAction: URIRef + InsuranceAgency: URIRef + Intangible: URIRef + Integer: URIRef + InteractAction: URIRef + InteractionCounter: URIRef + InternetCafe: URIRef + InvestmentOrDeposit: URIRef + InviteAction: URIRef + Invoice: URIRef + ItemAvailability: URIRef + ItemList: URIRef + ItemListOrderType: URIRef + ItemPage: URIRef + JewelryStore: URIRef + JobPosting: URIRef + JoinAction: URIRef + LakeBodyOfWater: URIRef + Landform: URIRef + LandmarksOrHistoricalBuildings: URIRef + Language: URIRef + LeaveAction: URIRef + LegalService: URIRef + LegislativeBuilding: URIRef + LendAction: URIRef + Library: URIRef + LikeAction: URIRef + LiquorStore: URIRef + ListItem: URIRef + ListenAction: URIRef + LiteraryEvent: URIRef + LiveBlogPosting: URIRef + LoanOrCredit: URIRef + LocalBusiness: URIRef + LocationFeatureSpecification: URIRef + LockerDelivery: URIRef + Locksmith: URIRef + LodgingBusiness: URIRef + LodgingReservation: URIRef + LoseAction: URIRef + Map: URIRef + MapCategoryType: URIRef + MarryAction: URIRef + Mass: URIRef + MediaGallery: URIRef + MediaObject: URIRef + MediaSubscription: URIRef + MedicalOrganization: URIRef + MeetingRoom: URIRef + MensClothingStore: URIRef + Menu: URIRef + MenuItem: URIRef + MenuSection: URIRef + Message: URIRef + MiddleSchool: URIRef + MobileApplication: URIRef + MobilePhoneStore: URIRef + MonetaryAmount: URIRef + MonetaryAmountDistribution: URIRef + Mosque: URIRef + Motel: URIRef + MotorcycleDealer: URIRef + MotorcycleRepair: URIRef + Mountain: URIRef + MoveAction: URIRef + Movie: URIRef + MovieClip: URIRef + MovieRentalStore: URIRef + MovieSeries: URIRef + MovieTheater: URIRef + MovingCompany: URIRef + Museum: URIRef + MusicAlbum: URIRef + MusicAlbumProductionType: URIRef + MusicAlbumReleaseType: URIRef + MusicComposition: URIRef + MusicEvent: URIRef + MusicGroup: URIRef + MusicPlaylist: URIRef + MusicRecording: URIRef + MusicRelease: URIRef + MusicReleaseFormatType: URIRef + MusicStore: URIRef + MusicVenue: URIRef + MusicVideoObject: URIRef + NGO: URIRef + NailSalon: URIRef + NewsArticle: URIRef + NightClub: URIRef + Notary: URIRef + NoteDigitalDocument: URIRef + Number: URIRef + NutritionInformation: URIRef + Occupation: URIRef + OceanBodyOfWater: URIRef + Offer: URIRef + OfferCatalog: URIRef + OfferItemCondition: URIRef + OfficeEquipmentStore: URIRef + OnDemandEvent: URIRef + OpeningHoursSpecification: URIRef + Order: URIRef + OrderAction: URIRef + OrderItem: URIRef + OrderStatus: URIRef + Organization: URIRef + OrganizationRole: URIRef + OrganizeAction: URIRef + OutletStore: URIRef + OwnershipInfo: URIRef + PaintAction: URIRef + Painting: URIRef + ParcelDelivery: URIRef + ParcelService: URIRef + ParentAudience: URIRef + Park: URIRef + ParkingFacility: URIRef + PawnShop: URIRef + PayAction: URIRef + PaymentCard: URIRef + PaymentChargeSpecification: URIRef + PaymentMethod: URIRef + PaymentService: URIRef + PaymentStatusType: URIRef + PeopleAudience: URIRef + PerformAction: URIRef + PerformanceRole: URIRef + PerformingArtsTheater: URIRef + PerformingGroup: URIRef + Periodical: URIRef + Permit: URIRef + Person: URIRef + PetStore: URIRef + Pharmacy: URIRef + Photograph: URIRef + PhotographAction: URIRef + Physician: URIRef + Place: URIRef + PlaceOfWorship: URIRef + PlanAction: URIRef + PlayAction: URIRef + Playground: URIRef + Plumber: URIRef + PoliceStation: URIRef + Pond: URIRef + PostOffice: URIRef + PostalAddress: URIRef + PreOrderAction: URIRef + PrependAction: URIRef + Preschool: URIRef + PresentationDigitalDocument: URIRef + PriceSpecification: URIRef + Product: URIRef + ProductModel: URIRef + ProfessionalService: URIRef + ProfilePage: URIRef + ProgramMembership: URIRef + PropertyValue: URIRef + PropertyValueSpecification: URIRef + PublicSwimmingPool: URIRef + PublicationEvent: URIRef + PublicationIssue: URIRef + PublicationVolume: URIRef + QAPage: URIRef + QualitativeValue: URIRef + QuantitativeValue: URIRef + QuantitativeValueDistribution: URIRef + Quantity: URIRef + Question: URIRef + QuoteAction: URIRef + RVPark: URIRef + RadioChannel: URIRef + RadioClip: URIRef + RadioEpisode: URIRef + RadioSeason: URIRef + RadioSeries: URIRef + RadioStation: URIRef + Rating: URIRef + ReactAction: URIRef + ReadAction: URIRef + RealEstateAgent: URIRef + ReceiveAction: URIRef + Recipe: URIRef + RecyclingCenter: URIRef + RegisterAction: URIRef + RejectAction: URIRef + RentAction: URIRef + RentalCarReservation: URIRef + ReplaceAction: URIRef + ReplyAction: URIRef + Report: URIRef + Reservation: URIRef + ReservationPackage: URIRef + ReservationStatusType: URIRef + ReserveAction: URIRef + Reservoir: URIRef + Residence: URIRef + Resort: URIRef + Restaurant: URIRef + RestrictedDiet: URIRef + ResumeAction: URIRef + ReturnAction: URIRef + Review: URIRef + ReviewAction: URIRef + RiverBodyOfWater: URIRef + Role: URIRef + RoofingContractor: URIRef + Room: URIRef + RsvpAction: URIRef + RsvpResponseType: URIRef + SaleEvent: URIRef + ScheduleAction: URIRef + ScholarlyArticle: URIRef + School: URIRef + ScreeningEvent: URIRef + Sculpture: URIRef + SeaBodyOfWater: URIRef + SearchAction: URIRef + SearchResultsPage: URIRef + Season: URIRef + Seat: URIRef + SelfStorage: URIRef + SellAction: URIRef + SendAction: URIRef + Series: URIRef + Service: URIRef + ServiceChannel: URIRef + ShareAction: URIRef + ShoeStore: URIRef + ShoppingCenter: URIRef + SingleFamilyResidence: URIRef + SiteNavigationElement: URIRef + SkiResort: URIRef + SocialEvent: URIRef + SocialMediaPosting: URIRef + SoftwareApplication: URIRef + SoftwareSourceCode: URIRef + SomeProducts: URIRef + SpeakableSpecification: URIRef + Specialty: URIRef + SportingGoodsStore: URIRef + SportsActivityLocation: URIRef + SportsClub: URIRef + SportsEvent: URIRef + SportsOrganization: URIRef + SportsTeam: URIRef + SpreadsheetDigitalDocument: URIRef + StadiumOrArena: URIRef + State: URIRef + SteeringPositionValue: URIRef + Store: URIRef + StructuredValue: URIRef + SubscribeAction: URIRef + SubwayStation: URIRef + Suite: URIRef + SuspendAction: URIRef + Synagogue: URIRef + TVClip: URIRef + TVEpisode: URIRef + TVSeason: URIRef + TVSeries: URIRef + Table: URIRef + TakeAction: URIRef + TattooParlor: URIRef + Taxi: URIRef + TaxiReservation: URIRef + TaxiService: URIRef + TaxiStand: URIRef + TechArticle: URIRef + TelevisionChannel: URIRef + TelevisionStation: URIRef + TennisComplex: URIRef + Text: URIRef + TextDigitalDocument: URIRef + TheaterEvent: URIRef + TheaterGroup: URIRef + Thing: URIRef + Ticket: URIRef + TieAction: URIRef + Time: URIRef + TipAction: URIRef + TireShop: URIRef + TouristAttraction: URIRef + TouristInformationCenter: URIRef + ToyStore: URIRef + TrackAction: URIRef + TradeAction: URIRef + TrainReservation: URIRef + TrainStation: URIRef + TrainTrip: URIRef + TransferAction: URIRef + TravelAction: URIRef + TravelAgency: URIRef + Trip: URIRef + TypeAndQuantityNode: URIRef + URL: URIRef + UnRegisterAction: URIRef + UnitPriceSpecification: URIRef + UpdateAction: URIRef + UseAction: URIRef + UserBlocks: URIRef + UserCheckins: URIRef + UserComments: URIRef + UserDownloads: URIRef + UserInteraction: URIRef + UserLikes: URIRef + UserPageVisits: URIRef + UserPlays: URIRef + UserPlusOnes: URIRef + UserTweets: URIRef + Vehicle: URIRef + VideoGallery: URIRef + VideoGame: URIRef + VideoGameClip: URIRef + VideoGameSeries: URIRef + VideoObject: URIRef + ViewAction: URIRef + VisualArtsEvent: URIRef + VisualArtwork: URIRef + Volcano: URIRef + VoteAction: URIRef + WPAdBlock: URIRef + WPFooter: URIRef + WPHeader: URIRef + WPSideBar: URIRef + WantAction: URIRef + WarrantyPromise: URIRef + WarrantyScope: URIRef + WatchAction: URIRef + Waterfall: URIRef + WearAction: URIRef + WebApplication: URIRef + WebPage: URIRef + WebPageElement: URIRef + WebSite: URIRef + WholesaleStore: URIRef + WinAction: URIRef + Winery: URIRef + WorkersUnion: URIRef + WriteAction: URIRef + Zoo: URIRef diff --git a/mypy-stubs/rdflib/namespace/_SH.pyi b/mypy-stubs/rdflib/namespace/_SH.pyi new file mode 100644 index 0000000..d755656 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_SH.pyi @@ -0,0 +1,183 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class SH(DefinedNamespace): + alternativePath: URIRef + annotationProperty: URIRef + annotationValue: URIRef + annotationVarName: URIRef + ask: URIRef + closed: URIRef + condition: URIRef + conforms: URIRef + construct: URIRef + datatype: URIRef + deactivated: URIRef + declare: URIRef + defaultValue: URIRef + description: URIRef + detail: URIRef + disjoint: URIRef + entailment: URIRef + equals: URIRef + expression: URIRef + filterShape: URIRef + flags: URIRef + focusNode: URIRef + group: URIRef + hasValue: URIRef + ignoredProperties: URIRef + intersection: URIRef + inversePath: URIRef + js: URIRef + jsFunctionName: URIRef + jsLibrary: URIRef + jsLibraryURL: URIRef + labelTemplate: URIRef + languageIn: URIRef + lessThan: URIRef + lessThanOrEquals: URIRef + maxCount: URIRef + maxExclusive: URIRef + maxInclusive: URIRef + maxLength: URIRef + message: URIRef + minCount: URIRef + minExclusive: URIRef + minInclusive: URIRef + minLength: URIRef + name: URIRef + namespace: URIRef + node: URIRef + nodeKind: URIRef + nodeValidator: URIRef + nodes: URIRef + object: URIRef + oneOrMorePath: URIRef + optional: URIRef + order: URIRef + parameter: URIRef + path: URIRef + pattern: URIRef + predicate: URIRef + prefix: URIRef + prefixes: URIRef + property: URIRef + propertyValidator: URIRef + qualifiedMaxCount: URIRef + qualifiedMinCount: URIRef + qualifiedValueShape: URIRef + qualifiedValueShapesDisjoint: URIRef + result: URIRef + resultAnnotation: URIRef + resultMessage: URIRef + resultPath: URIRef + resultSeverity: URIRef + returnType: URIRef + rule: URIRef + select: URIRef + severity: URIRef + shapesGraph: URIRef + shapesGraphWellFormed: URIRef + sourceConstraint: URIRef + sourceConstraintComponent: URIRef + sourceShape: URIRef + sparql: URIRef + subject: URIRef + suggestedShapesGraph: URIRef + target: URIRef + targetClass: URIRef + targetNode: URIRef + targetObjectsOf: URIRef + targetSubjectsOf: URIRef + union: URIRef + uniqueLang: URIRef + update: URIRef + validator: URIRef + value: URIRef + xone: URIRef + zeroOrMorePath: URIRef + zeroOrOnePath: URIRef + AbstractResult: URIRef + ConstraintComponent: URIRef + Function: URIRef + JSConstraint: URIRef + JSExecutable: URIRef + JSFunction: URIRef + JSLibrary: URIRef + JSRule: URIRef + JSTarget: URIRef + JSTargetType: URIRef + JSValidator: URIRef + NodeKind: URIRef + NodeShape: URIRef + Parameter: URIRef + Parameterizable: URIRef + PrefixDeclaration: URIRef + PropertyGroup: URIRef + PropertyShape: URIRef + ResultAnnotation: URIRef + Rule: URIRef + SPARQLAskExecutable: URIRef + SPARQLAskValidator: URIRef + SPARQLConstraint: URIRef + SPARQLConstructExecutable: URIRef + SPARQLExecutable: URIRef + SPARQLFunction: URIRef + SPARQLRule: URIRef + SPARQLSelectExecutable: URIRef + SPARQLSelectValidator: URIRef + SPARQLTarget: URIRef + SPARQLTargetType: URIRef + SPARQLUpdateExecutable: URIRef + Severity: URIRef + Shape: URIRef + Target: URIRef + TargetType: URIRef + TripleRule: URIRef + ValidationReport: URIRef + ValidationResult: URIRef + Validator: URIRef + this: URIRef + AndConstraintComponent: URIRef + ClassConstraintComponent: URIRef + ClosedConstraintComponent: URIRef + DatatypeConstraintComponent: URIRef + DisjointConstraintComponent: URIRef + EqualsConstraintComponent: URIRef + ExpressionConstraintComponent: URIRef + HasValueConstraintComponent: URIRef + InConstraintComponent: URIRef + JSConstraintComponent: URIRef + LanguageInConstraintComponent: URIRef + LessThanConstraintComponent: URIRef + LessThanOrEqualsConstraintComponent: URIRef + MaxCountConstraintComponent: URIRef + MaxExclusiveConstraintComponent: URIRef + MaxInclusiveConstraintComponent: URIRef + MaxLengthConstraintComponent: URIRef + MinCountConstraintComponent: URIRef + MinExclusiveConstraintComponent: URIRef + MinInclusiveConstraintComponent: URIRef + MinLengthConstraintComponent: URIRef + NodeConstraintComponent: URIRef + NodeKindConstraintComponent: URIRef + NotConstraintComponent: URIRef + OrConstraintComponent: URIRef + PatternConstraintComponent: URIRef + PropertyConstraintComponent: URIRef + QualifiedMaxCountConstraintComponent: URIRef + QualifiedMinCountConstraintComponent: URIRef + SPARQLConstraintComponent: URIRef + UniqueLangConstraintComponent: URIRef + XoneConstraintComponent: URIRef + BlankNode: URIRef + BlankNodeOrIRI: URIRef + BlankNodeOrLiteral: URIRef + IRI: URIRef + IRIOrLiteral: URIRef + Literal: URIRef + Info: URIRef + Violation: URIRef + Warning: URIRef diff --git a/mypy-stubs/rdflib/namespace/_SKOS.pyi b/mypy-stubs/rdflib/namespace/_SKOS.pyi new file mode 100644 index 0000000..a52fcc4 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_SKOS.pyi @@ -0,0 +1,37 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class SKOS(DefinedNamespace): + altLabel: URIRef + broadMatch: URIRef + broader: URIRef + broaderTransitive: URIRef + changeNote: URIRef + closeMatch: URIRef + definition: URIRef + editorialNote: URIRef + exactMatch: URIRef + example: URIRef + hasTopConcept: URIRef + hiddenLabel: URIRef + historyNote: URIRef + inScheme: URIRef + mappingRelation: URIRef + member: URIRef + memberList: URIRef + narrowMatch: URIRef + narrower: URIRef + narrowerTransitive: URIRef + notation: URIRef + note: URIRef + prefLabel: URIRef + related: URIRef + relatedMatch: URIRef + scopeNote: URIRef + semanticRelation: URIRef + topConceptOf: URIRef + Collection: URIRef + Concept: URIRef + ConceptScheme: URIRef + OrderedCollection: URIRef diff --git a/mypy-stubs/rdflib/namespace/_SOSA.pyi b/mypy-stubs/rdflib/namespace/_SOSA.pyi new file mode 100644 index 0000000..465a729 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_SOSA.pyi @@ -0,0 +1,41 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class SOSA(DefinedNamespace): + ActuatableProperty: URIRef + Actuation: URIRef + Actuator: URIRef + FeatureOfInterest: URIRef + ObservableProperty: URIRef + Observation: URIRef + Platform: URIRef + Procedure: URIRef + Result: URIRef + Sample: URIRef + Sampler: URIRef + Sampling: URIRef + Sensor: URIRef + hasSimpleResult: URIRef + resultTime: URIRef + actsOnProperty: URIRef + hasFeatureOfInterest: URIRef + hasResult: URIRef + hasSample: URIRef + hosts: URIRef + isActedOnBy: URIRef + isFeatureOfInterestOf: URIRef + isHostedBy: URIRef + isObservedBy: URIRef + isResultOf: URIRef + isSampleOf: URIRef + madeActuation: URIRef + madeByActuator: URIRef + madeBySampler: URIRef + madeBySensor: URIRef + madeObservation: URIRef + madeSampling: URIRef + observedProperty: URIRef + observes: URIRef + phenomenonTime: URIRef + usedProcedure: URIRef diff --git a/mypy-stubs/rdflib/namespace/_SSN.pyi b/mypy-stubs/rdflib/namespace/_SSN.pyi new file mode 100644 index 0000000..aa82b50 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_SSN.pyi @@ -0,0 +1,26 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class SSN(DefinedNamespace): + Deployment: URIRef + Input: URIRef + Output: URIRef + Property: URIRef + Stimulus: URIRef + System: URIRef + wasOriginatedBy: URIRef + deployedOnPlatform: URIRef + deployedSystem: URIRef + detects: URIRef + forProperty: URIRef + hasDeployment: URIRef + hasInput: URIRef + hasOutput: URIRef + hasProperty: URIRef + hasSubSystem: URIRef + implementedBy: URIRef + implements: URIRef + inDeployment: URIRef + isPropertyOf: URIRef + isProxyFor: URIRef diff --git a/mypy-stubs/rdflib/namespace/_TIME.pyi b/mypy-stubs/rdflib/namespace/_TIME.pyi new file mode 100644 index 0000000..2321ca3 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_TIME.pyi @@ -0,0 +1,100 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class TIME(DefinedNamespace): + generalDay: URIRef + generalMonth: URIRef + generalYear: URIRef + DateTimeDescription: URIRef + DateTimeInterval: URIRef + DayOfWeek: URIRef + Duration: URIRef + DurationDescription: URIRef + GeneralDateTimeDescription: URIRef + GeneralDurationDescription: URIRef + Instant: URIRef + Interval: URIRef + MonthOfYear: URIRef + ProperInterval: URIRef + TRS: URIRef + TemporalDuration: URIRef + TemporalEntity: URIRef + TemporalPosition: URIRef + TemporalUnit: URIRef + TimePosition: URIRef + TimeZone: URIRef + day: URIRef + dayOfYear: URIRef + days: URIRef + hasXSDDuration: URIRef + hour: URIRef + hours: URIRef + inXSDDate: URIRef + inXSDDateTimeStamp: URIRef + inXSDgYear: URIRef + inXSDgYearMonth: URIRef + minute: URIRef + minutes: URIRef + month: URIRef + months: URIRef + nominalPosition: URIRef + numericDuration: URIRef + numericPosition: URIRef + second: URIRef + seconds: URIRef + week: URIRef + weeks: URIRef + year: URIRef + years: URIRef + January: URIRef + Year: URIRef + inXSDDateTime: URIRef + xsdDateTime: URIRef + hasTRS: URIRef + after: URIRef + dayOfWeek: URIRef + hasBeginning: URIRef + hasDateTimeDescription: URIRef + hasDuration: URIRef + hasDurationDescription: URIRef + hasEnd: URIRef + hasTemporalDuration: URIRef + hasTime: URIRef + inDateTime: URIRef + inTemporalPosition: URIRef + inTimePosition: URIRef + inside: URIRef + intervalAfter: URIRef + intervalBefore: URIRef + intervalContains: URIRef + intervalDisjoint: URIRef + intervalDuring: URIRef + intervalEquals: URIRef + intervalFinishedBy: URIRef + intervalFinishes: URIRef + intervalIn: URIRef + intervalMeets: URIRef + intervalMetBy: URIRef + intervalOverlappedBy: URIRef + intervalOverlaps: URIRef + intervalStartedBy: URIRef + intervalStarts: URIRef + monthOfYear: URIRef + timeZone: URIRef + unitType: URIRef + before: URIRef + Friday: URIRef + Monday: URIRef + Saturday: URIRef + Sunday: URIRef + Thursday: URIRef + Tuesday: URIRef + Wednesday: URIRef + unitDay: URIRef + unitHour: URIRef + unitMinute: URIRef + unitMonth: URIRef + unitSecond: URIRef + unitWeek: URIRef + unitYear: URIRef diff --git a/mypy-stubs/rdflib/namespace/_VOID.pyi b/mypy-stubs/rdflib/namespace/_VOID.pyi new file mode 100644 index 0000000..90c00d8 --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_VOID.pyi @@ -0,0 +1,35 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class VOID(DefinedNamespace): + classPartition: URIRef + classes: URIRef + dataDump: URIRef + distinctObjects: URIRef + distinctSubjects: URIRef + documents: URIRef + entities: URIRef + exampleResource: URIRef + feature: URIRef + inDataset: URIRef + linkPredicate: URIRef + objectsTarget: URIRef + openSearchDescription: URIRef + properties: URIRef + property: URIRef + propertyPartition: URIRef + rootResource: URIRef + sparqlEndpoint: URIRef + subjectsTarget: URIRef + subset: URIRef + target: URIRef + triples: URIRef + uriLookupEndpoint: URIRef + uriRegexPattern: URIRef + uriSpace: URIRef + vocabulary: URIRef + Dataset: URIRef + DatasetDescription: URIRef + Linkset: URIRef + TechnicalFeature: URIRef diff --git a/mypy-stubs/rdflib/namespace/_XSD.pyi b/mypy-stubs/rdflib/namespace/_XSD.pyi new file mode 100644 index 0000000..d9f948f --- /dev/null +++ b/mypy-stubs/rdflib/namespace/_XSD.pyi @@ -0,0 +1,77 @@ +from rdflib.namespace import DefinedNamespace as DefinedNamespace +from rdflib.namespace import Namespace as Namespace +from rdflib.term import URIRef as URIRef + +class XSD(DefinedNamespace): + ENTITIES: URIRef + ENTITY: URIRef + ID: URIRef + IDREF: URIRef + IDREFS: URIRef + NCName: URIRef + NMTOKEN: URIRef + NMTOKENS: URIRef + NOTATION: URIRef + Name: URIRef + QName: URIRef + anyURI: URIRef + base64Binary: URIRef + boolean: URIRef + byte: URIRef + date: URIRef + dateTime: URIRef + dateTimeStamp: URIRef + dayTimeDuration: URIRef + decimal: URIRef + double: URIRef + duration: URIRef + float: URIRef + gDay: URIRef + gMonth: URIRef + gMonthDay: URIRef + gYear: URIRef + gYearMonth: URIRef + hexBinary: URIRef + int: URIRef + integer: URIRef + language: URIRef + long: URIRef + negativeInteger: URIRef + nonNegativeInteger: URIRef + nonPositiveInteger: URIRef + normalizedString: URIRef + positiveInteger: URIRef + short: URIRef + string: URIRef + time: URIRef + token: URIRef + unsignedByte: URIRef + unsignedInt: URIRef + unsignedLong: URIRef + unsignedShort: URIRef + yearMonthDuration: URIRef + ordered: URIRef + bounded: URIRef + cardinality: URIRef + numeric: URIRef + length: URIRef + minLength: URIRef + maxLength: URIRef + pattern: URIRef + enumeration: URIRef + whiteSpace: URIRef + maxExclusive: URIRef + maxInclusive: URIRef + minExclusive: URIRef + minInclusive: URIRef + totalDigits: URIRef + fractionDigits: URIRef + Assertions: URIRef + explicitTimezone: URIRef + year: URIRef + month: URIRef + day: URIRef + hour: URIRef + minute: URIRef + second: URIRef + timezoneOffset: URIRef diff --git a/mypy-stubs/rdflib/namespace/__init__.pyi b/mypy-stubs/rdflib/namespace/__init__.pyi new file mode 100644 index 0000000..e5342fd --- /dev/null +++ b/mypy-stubs/rdflib/namespace/__init__.pyi @@ -0,0 +1,85 @@ +from typing import Any, Tuple + +from rdflib.term import URIRef + +__all__ = [ + "split_uri", + "Namespace", + "ClosedNamespace", + "RDF", + "RDFS", + "CSVW", + "DC", + "DCAT", + "DCTERMS", + "DOAP", + "FOAF", + "ODRL2", + "ORG", + "OWL", + "PROF", + "PROV", + "QB", + "SDO", + "SH", + "SKOS", + "SOSA", + "SSN", + "TIME", + "VOID", + "XSD", + "OWL", +] + +class Namespace(str): + @property + def title(self) -> URIRef: ... + def term(self, name: Any) -> URIRef: ... + def __getitem__(self, key: Any) -> URIRef: ... + def __getattr__(self, name: str) -> URIRef: ... + +class URIPattern(str): + def format(self, *args: Any, **kwargs: Any) -> str: ... + +class DefinedNamespaceMeta(type): + def __getitem__(cls, name: Any, default: Any | None = ...) -> URIRef: ... + def __getattr__(cls, name: Any) -> URIRef: ... + def __contains__(cls, item: Any) -> bool: ... + +class DefinedNamespace(metaclass=DefinedNamespaceMeta): + def __init__(self) -> None: ... + +class ClosedNamespace(Namespace): + def __new__(cls, uri: Any, terms: Any) -> ClosedNamespace: ... + @property + def uri(self) -> str: ... + +NAME_START_CATEGORIES = ["Ll", "Lu", "Lo", "Lt", "Nl"] +SPLIT_START_CATEGORIES = NAME_START_CATEGORIES + ["Nd"] + +XMLNS = "http://www.w3.org/XML/1998/namespace" + +def split_uri(uri: Any, split_start: Any = ...) -> Tuple[str, str]: ... + +from rdflib.namespace._CSVW import CSVW +from rdflib.namespace._DC import DC +from rdflib.namespace._DCAT import DCAT +from rdflib.namespace._DCTERMS import DCTERMS +from rdflib.namespace._DOAP import DOAP +from rdflib.namespace._FOAF import FOAF +from rdflib.namespace._ODRL2 import ODRL2 +from rdflib.namespace._ORG import ORG +from rdflib.namespace._OWL import OWL +from rdflib.namespace._PROF import PROF +from rdflib.namespace._PROV import PROV +from rdflib.namespace._QB import QB +from rdflib.namespace._RDF import RDF +from rdflib.namespace._RDFS import RDFS +from rdflib.namespace._SDO import SDO +from rdflib.namespace._SH import SH +from rdflib.namespace._SKOS import SKOS +from rdflib.namespace._SOSA import SOSA +from rdflib.namespace._SSN import SSN +from rdflib.namespace._TIME import TIME +from rdflib.namespace._VOID import VOID +from rdflib.namespace._XSD import XSD diff --git a/mypy-stubs/rdflib/parser.pyi b/mypy-stubs/rdflib/parser.pyi new file mode 100644 index 0000000..4c628be --- /dev/null +++ b/mypy-stubs/rdflib/parser.pyi @@ -0,0 +1,5 @@ +from typing import Any + +class Parser: + def __init__(self) -> None: ... + def parse(self, source: Any, sink: Any) -> None: ... diff --git a/mypy-stubs/rdflib/paths.pyi b/mypy-stubs/rdflib/paths.pyi new file mode 100644 index 0000000..9bea179 --- /dev/null +++ b/mypy-stubs/rdflib/paths.pyi @@ -0,0 +1,24 @@ +from collections.abc import Generator +from typing import Any, Callable, Union + +from rdflib.term import Node as Node +from rdflib.term import URIRef as URIRef + +ZeroOrMore: str +OneOrMore: str +ZeroOrOne: str + +class Path: + __or__: Callable[[Path, Union["URIRef", "Path"]], "AlternativePath"] + __invert__: Callable[[Path], "InvPath"] + __neg__: Callable[[Path], "NegatedPath"] + __truediv__: Callable[[Path, Union["URIRef", "Path"]], "SequencePath"] + __mul__: Callable[[Path, str], "MulPath"] + def __hash__(self) -> int: ... + def __lt__(self, other: Any) -> bool: ... + +class InvPath(Path): ... +class SequencePath(Path): ... +class AlternativePath(Path): ... +class MulPath(Path): ... +class NegatedPath(Path): ... diff --git a/mypy-stubs/rdflib/plugin.pyi b/mypy-stubs/rdflib/plugin.pyi new file mode 100644 index 0000000..d6f840d --- /dev/null +++ b/mypy-stubs/rdflib/plugin.pyi @@ -0,0 +1,8 @@ +from typing import Any, Type, TypeVar + +def register(name: str, kind: Any, module_path: str, class_name: str) -> None: ... + +PluginT = TypeVar("PluginT") + +def get(name: str, kind: Type[PluginT]) -> Type[PluginT]: ... +def plugins(name: Any | None = ..., kind: Any | None = ...) -> None: ... diff --git a/typeshed/rdflib/plugins/__init__.pyi b/mypy-stubs/rdflib/plugins/__init__.pyi similarity index 99% rename from typeshed/rdflib/plugins/__init__.pyi rename to mypy-stubs/rdflib/plugins/__init__.pyi index e856e17..fc4e2d1 100644 --- a/typeshed/rdflib/plugins/__init__.pyi +++ b/mypy-stubs/rdflib/plugins/__init__.pyi @@ -1,4 +1,3 @@ # Stubs for rdflib.plugins (Python 3.5) # # NOTE: This dynamically typed stub was automatically generated by stubgen. - diff --git a/typeshed/rdflib/plugins/parsers/__init__.pyi b/mypy-stubs/rdflib/plugins/parsers/__init__.pyi similarity index 99% rename from typeshed/rdflib/plugins/parsers/__init__.pyi rename to mypy-stubs/rdflib/plugins/parsers/__init__.pyi index 3f18710..589759a 100644 --- a/typeshed/rdflib/plugins/parsers/__init__.pyi +++ b/mypy-stubs/rdflib/plugins/parsers/__init__.pyi @@ -1,4 +1,3 @@ # Stubs for rdflib.plugins.parsers (Python 3.5) # # NOTE: This dynamically typed stub was automatically generated by stubgen. - diff --git a/mypy-stubs/rdflib/plugins/parsers/notation3.pyi b/mypy-stubs/rdflib/plugins/parsers/notation3.pyi new file mode 100644 index 0000000..40932a7 --- /dev/null +++ b/mypy-stubs/rdflib/plugins/parsers/notation3.pyi @@ -0,0 +1 @@ +class BadSyntax(SyntaxError): ... diff --git a/mypy-stubs/rdflib/query.pyi b/mypy-stubs/rdflib/query.pyi new file mode 100644 index 0000000..73f4008 --- /dev/null +++ b/mypy-stubs/rdflib/query.pyi @@ -0,0 +1,42 @@ +from typing import IO, Any, Dict, Iterator, List, Mapping, Optional, Tuple, overload + +from rdflib import URIRef, Variable +from rdflib.term import Identifier +from typing_extensions import SupportsIndex + +class ResultRow(Tuple["Identifier", ...]): + def __new__( + cls, values: Mapping[Variable, Identifier], labels: List[Variable] + ) -> ResultRow: ... + def __getattr__(self, name: str) -> Identifier: ... + @overload + def __getitem__(self, name: str) -> Identifier: ... + @overload + def __getitem__(self, __x: SupportsIndex) -> Identifier: ... + @overload + def __getitem__(self, __x: slice) -> Tuple[Identifier, ...]: ... + def get(self, name: str, default: Any | None = ...) -> Identifier: ... + def asdict(self) -> Dict[str, Identifier]: ... + +class Result: + type: Any + vars: Any + askAnswer: Any + graph: Any + def __init__(self, type_: str) -> None: ... + bindings: Any + def __iter__(self) -> Iterator[bool | ResultRow]: ... + @staticmethod + def parse( + source: IO[Any] | None = ..., + format: str | None = ..., + content_type: str | None = ..., + **kwargs: Any + ) -> Result: ... + def serialize( + self, + destination: str | IO[Any] | None = ..., + encoding: str = ..., + format: str = ..., + **args: Any + ) -> Optional[bytes]: ... diff --git a/mypy-stubs/rdflib/resource.pyi b/mypy-stubs/rdflib/resource.pyi new file mode 100644 index 0000000..e520dbe --- /dev/null +++ b/mypy-stubs/rdflib/resource.pyi @@ -0,0 +1,33 @@ +from typing import Any, Iterable, Iterator, Tuple + +from _typeshed import Incomplete +from rdflib.graph import Graph, Seq +from rdflib.term import Node + +class Resource: + def __init__(self, graph: Graph, subject: Node) -> None: ... + graph: Incomplete + identifier: Incomplete + def add(self, p: Node, o: Node) -> None: ... + def remove(self, p: Node, o: Node | None = ...) -> None: ... + def set(self, p: Node, o: Node) -> None: ... + def subjects(self, predicate: Any | None = ...) -> Iterable[Node]: ... + def predicates(self, o: Incomplete | None = ...) -> Iterable[Node]: ... + def objects(self, predicate: Any | None = ...) -> Iterable[Node]: ... + def subject_predicates(self) -> Iterator[Tuple[Node, Node]]: ... + def subject_objects(self) -> Iterator[Tuple[Node, Node]]: ... + def predicate_objects(self) -> Iterator[Tuple[Node, Node]]: ... + def value( + self, p: Node, o: Node | None = ..., default: Any | None = ..., any: bool = ... + ) -> Any: ... + def label(self) -> Any: ... + def comment(self) -> Any: ... + def items(self) -> Iterator[Any]: ... + def transitive_objects( + self, predicate: Node, remember: Any | None = ... + ) -> Iterator[Any]: ... + def transitive_subjects( + self, predicate: Node, remember: Any | None = ... + ) -> Iterator[Any]: ... + def seq(self) -> Seq | None: ... + def qname(self) -> Any: ... diff --git a/mypy-stubs/rdflib/term.pyi b/mypy-stubs/rdflib/term.pyi new file mode 100644 index 0000000..0830bdc --- /dev/null +++ b/mypy-stubs/rdflib/term.pyi @@ -0,0 +1,43 @@ +from typing import Any, Callable, Union + +class Node: ... + +class Identifier(Node, str): + def __new__(cls, value: Union[Any, str, None]) -> "Identifier": ... + def eq(self, other: Any) -> bool: ... + def neq(self, other: Any) -> bool: ... + +class IdentifiedNode(Identifier): ... + +class URIRef(IdentifiedNode): + def toPython(self) -> str: ... + def n3(self, namespace_manager: Any | None = ...) -> str: ... + def defrag(self) -> "URIRef": ... + def de_skolemize(self) -> "BNode": ... + +class Genid(URIRef): ... +class RDFLibGenid(Genid): ... + +class BNode(IdentifiedNode): + def toPython(self) -> str: ... + def n3(self, namespace_manager: Any | None = ...) -> str: ... + def skolemize( + self, authority: Any | None = ..., basepath: Any | None = ... + ) -> "RDFLibGenid": ... + +class Literal(Identifier): + def normalize(self) -> "Literal": ... + @property + def value(self) -> Any: ... + @property + def language(self) -> str | None: ... + @property + def datatype(self) -> Any: ... + def eq(self, other: Any) -> bool: ... + def neq(self, other: Any) -> bool: ... + def n3(self, namespace_manager: Any | None = ...) -> str: ... + def toPython(self) -> str: ... + +class Variable(Identifier): + def toPython(self) -> str: ... + def n3(self, namespace_manager: Any | None = ...) -> str: ... diff --git a/typeshed/ruamel/__init__.py b/mypy-stubs/ruamel/__init__.py similarity index 100% rename from typeshed/ruamel/__init__.py rename to mypy-stubs/ruamel/__init__.py diff --git a/typeshed/avro/__init__.pyi b/typeshed/avro/__init__.pyi deleted file mode 100644 index 39efba5..0000000 --- a/typeshed/avro/__init__.pyi +++ /dev/null @@ -1,10 +0,0 @@ -# Stubs for avro (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -# Names in __all__ with no definition: -# datafile -# io -# ipc -# protocol -# schema diff --git a/typeshed/avro/schema.pyi b/typeshed/avro/schema.pyi deleted file mode 100644 index 05f48e5..0000000 --- a/typeshed/avro/schema.pyi +++ /dev/null @@ -1,117 +0,0 @@ -# Stubs for avro.schema (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Union, Dict, List, Text - -PRIMITIVE_TYPES = ... # type: Any -NAMED_TYPES = ... # type: Any -VALID_TYPES = ... # type: Any -SCHEMA_RESERVED_PROPS = ... # type: Any -FIELD_RESERVED_PROPS = ... # type: Any -VALID_FIELD_SORT_ORDERS = ... # type: Any - -class AvroException(Exception): ... -class SchemaParseException(AvroException): ... - -class Schema: - type = ... # type: Any - def __init__(self, type, other_props=None): ... - props = ... # type: Any - other_props = ... # type: Any - def get_prop(self, key): ... - def set_prop(self, key, value): ... - def to_json(self, names): ... - -class Name: - def __init__(self, name_attr, space_attr, default_space): ... - def __eq__(self, other): ... - fullname = ... # type: Any - def get_space(self): ... - -class Names: - names = ... # type: Any - default_namespace = ... # type: Any - def __init__(self, default_namespace: Union[str, Text] = None) -> None: ... - def has_name(self, name_attr: Union[str, Text], space_attr: Union[str, Text]) -> bool: ... - def get_name(self, name_attr: Union[str, Text], space_attr: Union[str, Text]) -> Schema: ... - def prune_namespace(self, properties): ... - def add_name(self, name_attr, space_attr, new_schema): ... - -class NamedSchema(Schema): - def __init__(self, type, name, namespace=None, names=None, other_props=None): ... - def name_ref(self, names): ... - name = ... # type: Any - namespace = ... # type: Any - fullname = ... # type: Any - -class Field: - type = ... # type: Any - name = ... # type: Any - def __init__(self, type, name, has_default, default=None, order=None, names=None, doc=None, other_props=None): ... - default = ... # type: Any - has_default = ... # type: Any - order = ... # type: Any - doc = ... # type: Any - props = ... # type: Any - other_props = ... # type: Any - def get_prop(self, key): ... - def set_prop(self, key, value): ... - def to_json(self, names=None): ... - def __eq__(self, that): ... - -class PrimitiveSchema(Schema): - fullname = ... # type: Any - def __init__(self, type, other_props=None): ... - def to_json(self, names=None): ... - def __eq__(self, that): ... - -class FixedSchema(NamedSchema): - def __init__(self, name, namespace, size, names=None, other_props=None): ... - size = ... # type: Any - def to_json(self, names=None): ... - def __eq__(self, that): ... - -class EnumSchema(NamedSchema): - def __init__(self, name, namespace, symbols, names=None, doc=None, other_props=None): ... - symbols = ... # type: Any - doc = ... # type: Any - def to_json(self, names=None): ... - def __eq__(self, that): ... - -class ArraySchema(Schema): - def __init__(self, items, names=None, other_props=None): ... - items = ... # type: Any - def to_json(self, names=None): ... - def __eq__(self, that): ... - -class MapSchema(Schema): - def __init__(self, values, names=None, other_props=None): ... - values = ... # type: Any - def to_json(self, names=None): ... - def __eq__(self, that): ... - -class UnionSchema(Schema): - def __init__(self, schemas, names=None): ... - schemas = ... # type: Any - def to_json(self, names=None): ... - def __eq__(self, that): ... - -class ErrorUnionSchema(UnionSchema): - def __init__(self, schemas, names=None): ... - def to_json(self, names=None): ... - -class RecordSchema(NamedSchema): - @staticmethod - def make_field_objects(field_data, names): ... - def __init__(self, name, namespace, fields, names=None, schema_type='', doc=None, other_props=None): ... - fields = ... # type: Any - doc = ... # type: Any - @property - def fields_dict(self): ... - def to_json(self, names=None): ... - def __eq__(self, that): ... - -def get_other_props(all_props, reserved_props): ... -def make_avsc_object(json_data: Union[Dict, List, str], names: Names) -> Schema: ... -def parse(json_string): ... diff --git a/typeshed/cachecontrol/adapter.pyi b/typeshed/cachecontrol/adapter.pyi deleted file mode 100644 index 734fe14..0000000 --- a/typeshed/cachecontrol/adapter.pyi +++ /dev/null @@ -1,19 +0,0 @@ -# Stubs for cachecontrol.adapter (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from requests.adapters import HTTPAdapter -from .controller import CacheController as CacheController -from .cache import DictCache as DictCache -from .filewrapper import CallbackFileWrapper as CallbackFileWrapper - -class CacheControlAdapter(HTTPAdapter): - invalidating_methods = ... # type: Any - cache = ... # type: Any - heuristic = ... # type: Any - controller = ... # type: Any - def __init__(self, cache=None, cache_etags=True, controller_class=None, serializer=None, heuristic=None, *args, **kw): ... - def send(self, request, **kw): ... - def build_response(self, request, response, from_cache=False): ... - def close(self): ... diff --git a/typeshed/cachecontrol/cache.pyi b/typeshed/cachecontrol/cache.pyi deleted file mode 100644 index c4f507b..0000000 --- a/typeshed/cachecontrol/cache.pyi +++ /dev/null @@ -1,19 +0,0 @@ -# Stubs for cachecontrol.cache (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -class BaseCache: - def get(self, key): ... - def set(self, key, value): ... - def delete(self, key): ... - def close(self): ... - -class DictCache(BaseCache): - lock = ... # type: Any - data = ... # type: Any - def __init__(self, init_dict=None): ... - def get(self, key): ... - def set(self, key, value): ... - def delete(self, key): ... diff --git a/typeshed/cachecontrol/caches/file_cache.pyi b/typeshed/cachecontrol/caches/file_cache.pyi deleted file mode 100644 index 2d6ca0c..0000000 --- a/typeshed/cachecontrol/caches/file_cache.pyi +++ /dev/null @@ -1,22 +0,0 @@ -# Stubs for cachecontrol.caches.file_cache (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Callable -from ..cache import BaseCache as BaseCache -from ..controller import CacheController as CacheController - -class FileCache(BaseCache): - directory = ... # type: str - forever = ... # type: bool - filemode = ... # type: str - dirmode = ... # type: str - lock_class = ... # type: Callable - def __init__(self, directory: str, forever=False, filemode=384, dirmode=448, use_dir_lock=None, lock_class=None) -> None: ... - @staticmethod - def encode(x): ... - def get(self, key): ... - def set(self, key, value): ... - def delete(self, key): ... - -def url_to_file_path(url, filecache): ... diff --git a/typeshed/cachecontrol/controller.pyi b/typeshed/cachecontrol/controller.pyi deleted file mode 100644 index 1161e79..0000000 --- a/typeshed/cachecontrol/controller.pyi +++ /dev/null @@ -1,25 +0,0 @@ -# Stubs for cachecontrol.controller (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -#from .cache import DictCache as DictCache -#from .serialize import Serializer as Serializer - -logger = ... # type: Any -URI = ... # type: Any - -def parse_uri(uri): ... - -class CacheController: - cache = ... # type: Any - cache_etags = ... # type: Any - serializer = ... # type: Any - def __init__(self, cache=None, cache_etags=True, serializer=None): ... - @classmethod - def cache_url(https://github.com/cls,%20uri): ... - def parse_cache_control(self, headers): ... - def cached_request(self, request): ... - def conditional_headers(self, request): ... - def cache_response(self, request, response, body=None): ... - def update_cached_response(self, request, response): ... diff --git a/typeshed/cachecontrol/filewrapper.pyi b/typeshed/cachecontrol/filewrapper.pyi deleted file mode 100644 index d21df15..0000000 --- a/typeshed/cachecontrol/filewrapper.pyi +++ /dev/null @@ -1,8 +0,0 @@ -# Stubs for cachecontrol.filewrapper (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -class CallbackFileWrapper: - def __init__(self, fp, callback): ... - def __getattr__(self, name): ... - def read(self, amt=None): ... diff --git a/typeshed/cachecontrol/serialize.pyi b/typeshed/cachecontrol/serialize.pyi deleted file mode 100644 index a0f9eec..0000000 --- a/typeshed/cachecontrol/serialize.pyi +++ /dev/null @@ -1,10 +0,0 @@ -# Stubs for cachecontrol.serialize (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from .compat import HTTPResponse as HTTPResponse, pickle as pickle, text_type as text_type - -class Serializer: - def dumps(self, request, response, body=None): ... - def loads(self, request, data): ... - def prepare_response(self, request, cached): ... diff --git a/typeshed/cachecontrol/wrapper.pyi b/typeshed/cachecontrol/wrapper.pyi deleted file mode 100644 index 67ef6b4..0000000 --- a/typeshed/cachecontrol/wrapper.pyi +++ /dev/null @@ -1,14 +0,0 @@ -# Stubs for cachecontrol.wrapper (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Optional, Union -from .adapter import CacheControlAdapter as CacheControlAdapter -from .cache import DictCache, BaseCache -import requests - -def CacheControl(sess: requests.sessions.Session, - cache: Optional[Union[DictCache, BaseCache]] = None, - cache_etags: bool = True, - serializer=None, - heuristic=None) -> requests.sessions.Session: ... diff --git a/typeshed/future/__init__.pyi b/typeshed/future/__init__.pyi deleted file mode 100644 index e69de29..0000000 diff --git a/typeshed/future/utils/__init__.pyi b/typeshed/future/utils/__init__.pyi deleted file mode 100644 index a67c2a1..0000000 --- a/typeshed/future/utils/__init__.pyi +++ /dev/null @@ -1,61 +0,0 @@ -# Stubs for future.utils (Python 3) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -PY3: Any -PY2: Any -PY26: Any -PYPY: Any - -def python_2_unicode_compatible(cls): ... -def with_metaclass(meta: Any, *bases: Any): ... -def bstr(s: Any): ... -def bord(s: Any): ... - -def tobytes(s: Any): ... -def native_str_to_bytes(s: Any, encoding: str = ...): ... -def bytes_to_native_str(b: Any, encoding: str = ...): ... -def text_to_native_str(t: Any, encoding: Optional[Any] = ...): ... -def lrange(*args: Any, **kwargs: Any): ... -def lzip(*args: Any, **kwargs: Any): ... -def lmap(*args: Any, **kwargs: Any): ... -def lfilter(*args: Any, **kwargs: Any): ... - -def isidentifier(s: Any, dotted: bool = ...): ... -def viewitems(obj: Any, **kwargs: Any): ... -def viewkeys(obj: Any, **kwargs: Any): ... -def viewvalues(obj: Any, **kwargs: Any): ... -def iteritems(obj: Any, **kwargs: Any): ... -def iterkeys(obj: Any, **kwargs: Any): ... -def itervalues(obj: Any, **kwargs: Any): ... -def bind_method(cls, name: Any, func: Any) -> None: ... -def getexception(): ... -def raise_(tp: Any, value: Optional[Any] = ..., tb: Optional[Any] = ...) -> None: ... -def raise_from(exc: Any, cause: Any) -> None: ... -def raise_with_traceback(exc: Any, traceback: Any = ...) -> None: ... -reraise = raise_ - -def implements_iterator(cls): ... - -get_next: Any - -def encode_filename(filename: Any): ... -def is_new_style(cls): ... -native_str = str -native_bytes = bytes - -def istext(obj: Any): ... -def isbytes(obj: Any): ... -def isnewbytes(obj: Any): ... -def isint(obj: Any): ... -def native(obj: Any): ... - -exec_: Any - -def old_div(a: Any, b: Any): ... -def as_native_str(encoding: str = ...): ... -def listvalues(d: Any): ... -def listitems(d: Any): ... -def ensure_new_type(obj: Any): ... diff --git a/typeshed/galaxy/__init__.pyi b/typeshed/galaxy/__init__.pyi deleted file mode 100644 index aa2f6e6..0000000 --- a/typeshed/galaxy/__init__.pyi +++ /dev/null @@ -1,13 +0,0 @@ -# Stubs for galaxy (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -PROJECT_NAME = ... # type: str -PROJECT_OWNER = ... # type: str -PROJECT_USERAME = ... # type: str -PROJECT_URL = ... # type: str -PROJECT_AUTHOR = ... # type: str -PROJECT_EMAIL = ... # type: str -RAW_CONTENT_URL = ... # type: Any diff --git a/typeshed/galaxy/exceptions/__init__.pyi b/typeshed/galaxy/exceptions/__init__.pyi deleted file mode 100644 index e59ac08..0000000 --- a/typeshed/galaxy/exceptions/__init__.pyi +++ /dev/null @@ -1,143 +0,0 @@ -# Stubs for galaxy.exceptions (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from ..exceptions import error_codes as error_codes - -class MessageException(Exception): - status_code = ... # type: int - err_code = ... # type: Any - err_msg = ... # type: Any - type = ... # type: Any - extra_error_info = ... # type: Any - def __init__(self, err_msg: Optional[Any] = ..., type: str = ..., **extra_error_info) -> None: ... - -class ItemDeletionException(MessageException): ... -class ObjectInvalid(Exception): ... - -class ActionInputError(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - def __init__(self, err_msg, type: str = ...) -> None: ... - -class DuplicatedSlugException(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class DuplicatedIdentifierException(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class ObjectAttributeInvalidException(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class ObjectAttributeMissingException(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class MalformedId(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class MalformedContents(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class UnknownContentsType(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class RequestParameterMissingException(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class ToolMetaParameterException(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class ToolMissingException(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class RequestParameterInvalidException(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class AuthenticationFailed(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class AuthenticationRequired(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class ItemAccessibilityException(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class ItemOwnershipException(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class ConfigDoesNotAllowException(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class InsufficientPermissionsException(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class AdminRequiredException(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class ObjectNotFound(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class DeprecatedMethod(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class Conflict(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class ConfigurationError(Exception): - status_code = ... # type: int - err_code = ... # type: Any - -class InconsistentDatabase(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class InternalServerError(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class NotImplemented(MessageException): - status_code = ... # type: int - err_code = ... # type: Any - -class ContainerCLIError(Exception): - stdout = ... # type: Any - stderr = ... # type: Any - returncode = ... # type: Any - command = ... # type: Any - subprocess_command = ... # type: Any - def __init__(self, msg: Optional[Any] = ..., stdout: Optional[Any] = ..., stderr: Optional[Any] = ..., returncode: Optional[Any] = ..., command: Optional[Any] = ..., subprocess_command: Optional[Any] = ..., **kwargs) -> None: ... - -class ContainerNotFound(Exception): - container_id = ... # type: Any - def __init__(self, msg: Optional[Any] = ..., container_id: Optional[Any] = ..., **kwargs) -> None: ... - -class ContainerImageNotFound(Exception): - image = ... # type: Any - def __init__(self, msg: Optional[Any] = ..., image: Optional[Any] = ..., **kwargs) -> None: ... - -class ContainerRunError(Exception): - image = ... # type: Any - command = ... # type: Any - def __init__(self, msg: Optional[Any] = ..., image: Optional[Any] = ..., command: Optional[Any] = ..., **kwargs) -> None: ... diff --git a/typeshed/galaxy/exceptions/error_codes.pyi b/typeshed/galaxy/exceptions/error_codes.pyi deleted file mode 100644 index b25ca3e..0000000 --- a/typeshed/galaxy/exceptions/error_codes.pyi +++ /dev/null @@ -1,17 +0,0 @@ -# Stubs for galaxy.exceptions.error_codes (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -UNKNOWN_ERROR_MESSAGE = ... # type: str - -class ErrorCode: - code = ... # type: Any - default_error_message = ... # type: Any - def __init__(self, code, default_error_message) -> None: ... - def __int__(self): ... - -error_codes_json = ... # type: Any -name = ... # type: Any -error_code_obj = ... # type: Any diff --git a/typeshed/galaxy/jobs/__init__.pyi b/typeshed/galaxy/jobs/__init__.pyi deleted file mode 100644 index c65cfb4..0000000 --- a/typeshed/galaxy/jobs/__init__.pyi +++ /dev/null @@ -1,4 +0,0 @@ -# Stubs for galaxy.jobs (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - diff --git a/typeshed/galaxy/jobs/metrics/__init__.pyi b/typeshed/galaxy/jobs/metrics/__init__.pyi deleted file mode 100644 index 758ddc6..0000000 --- a/typeshed/galaxy/jobs/metrics/__init__.pyi +++ /dev/null @@ -1,38 +0,0 @@ -# Stubs for galaxy.jobs.metrics (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from ..metrics import formatting as formatting - -log = ... # type: Any -DEFAULT_FORMATTER = ... # type: Any - -class JobMetrics: - plugin_classes = ... # type: Any - default_job_instrumenter = ... # type: Any - job_instrumenters = ... # type: Any - def __init__(self, conf_file: Optional[Any] = ..., **kwargs) -> None: ... - def format(self, plugin, key, value): ... - def set_destination_conf_file(self, destination_id, conf_file): ... - def set_destination_conf_element(self, destination_id, element): ... - def set_destination_instrumenter(self, destination_id, job_instrumenter: Optional[Any] = ...): ... - def collect_properties(self, destination_id, job_id, job_directory): ... - -class NullJobInstrumenter: - def pre_execute_commands(self, job_directory): ... - def post_execute_commands(self, job_directory): ... - def collect_properties(self, job_id, job_directory): ... - -NULL_JOB_INSTRUMENTER = ... # type: Any - -class JobInstrumenter: - extra_kwargs = ... # type: Any - plugin_classes = ... # type: Any - plugins = ... # type: Any - def __init__(self, plugin_classes, plugins_source, **kwargs) -> None: ... - def pre_execute_commands(self, job_directory): ... - def post_execute_commands(self, job_directory): ... - def collect_properties(self, job_id, job_directory): ... - @staticmethod - def from_file(plugin_classes, conf_file, **kwargs): ... diff --git a/typeshed/galaxy/jobs/metrics/collectl/__init__.pyi b/typeshed/galaxy/jobs/metrics/collectl/__init__.pyi deleted file mode 100644 index c58636e..0000000 --- a/typeshed/galaxy/jobs/metrics/collectl/__init__.pyi +++ /dev/null @@ -1,4 +0,0 @@ -# Stubs for galaxy.jobs.metrics.collectl (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - diff --git a/typeshed/galaxy/jobs/metrics/collectl/cli.pyi b/typeshed/galaxy/jobs/metrics/collectl/cli.pyi deleted file mode 100644 index 88e3120..0000000 --- a/typeshed/galaxy/jobs/metrics/collectl/cli.pyi +++ /dev/null @@ -1,12 +0,0 @@ -# Stubs for galaxy.jobs.metrics.collectl.cli (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -class CollectlCli: - mode = ... # type: Any - command_args = ... # type: Any - def __init__(self, **kwargs) -> None: ... - def build_command_line(self): ... - def run(self, stdout: Any = ..., stderr: Any = ...): ... diff --git a/typeshed/galaxy/jobs/metrics/collectl/processes.pyi b/typeshed/galaxy/jobs/metrics/collectl/processes.pyi deleted file mode 100644 index ad6fbd8..0000000 --- a/typeshed/galaxy/jobs/metrics/collectl/processes.pyi +++ /dev/null @@ -1,24 +0,0 @@ -# Stubs for galaxy.jobs.metrics.collectl.processes (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -def generate_process_statistics(collectl_playback_cli, pid, statistics: Any = ...): ... - -class CollectlProcessSummarizer: - pid = ... # type: Any - statistics = ... # type: Any - columns_of_interest = ... # type: Any - tree_statistics = ... # type: Any - process_accum_statistics = ... # type: Any - interval_count = ... # type: int - def __init__(self, pid, statistics) -> None: ... - def handle_interval(self, interval): ... - def get_statistics(self): ... - -class CollectlProcessInterval: - rows = ... # type: Any - def __init__(self) -> None: ... - def row_is_in(self, row): ... - def add_row(self, row): ... diff --git a/typeshed/galaxy/jobs/metrics/collectl/stats.pyi b/typeshed/galaxy/jobs/metrics/collectl/stats.pyi deleted file mode 100644 index 39f0c8d..0000000 --- a/typeshed/galaxy/jobs/metrics/collectl/stats.pyi +++ /dev/null @@ -1,15 +0,0 @@ -# Stubs for galaxy.jobs.metrics.collectl.stats (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -class StatisticsTracker: - min = ... # type: Any - max = ... # type: Any - count = ... # type: int - sum = ... # type: int - def __init__(self) -> None: ... - def track(self, value): ... - @property - def avg(self): ... diff --git a/typeshed/galaxy/jobs/metrics/collectl/subsystems.pyi b/typeshed/galaxy/jobs/metrics/collectl/subsystems.pyi deleted file mode 100644 index 1da48e6..0000000 --- a/typeshed/galaxy/jobs/metrics/collectl/subsystems.pyi +++ /dev/null @@ -1,35 +0,0 @@ -# Stubs for galaxy.jobs.metrics.collectl.subsystems (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -class CollectlSubsystem: - @property - def command_line_arg(self): ... - @property - def name(self, job_directory): ... - -class ProcessesSubsystem(CollectlSubsystem): - command_line_arg = ... # type: str - name = ... # type: str - -class CpuSubsystem(CollectlSubsystem): - command_line_arg = ... # type: str - name = ... # type: str - -class DiskSubsystem(CollectlSubsystem): - command_line_arg = ... # type: str - name = ... # type: str - -class NetworkSubsystem(CollectlSubsystem): - command_line_arg = ... # type: str - name = ... # type: str - -class EnvironmentSubsystem(CollectlSubsystem): - command_line_arg = ... # type: str - name = ... # type: str - -class MemorySubsystem(CollectlSubsystem): - command_line_arg = ... # type: str - name = ... # type: str - -def get_subsystem(name): ... diff --git a/typeshed/galaxy/jobs/metrics/formatting.pyi b/typeshed/galaxy/jobs/metrics/formatting.pyi deleted file mode 100644 index ebc91b1..0000000 --- a/typeshed/galaxy/jobs/metrics/formatting.pyi +++ /dev/null @@ -1,8 +0,0 @@ -# Stubs for galaxy.jobs.metrics.formatting (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -class JobMetricFormatter: - def format(self, key, value): ... - -def seconds_to_str(value): ... diff --git a/typeshed/galaxy/jobs/metrics/instrumenters/__init__.pyi b/typeshed/galaxy/jobs/metrics/instrumenters/__init__.pyi deleted file mode 100644 index ede6717..0000000 --- a/typeshed/galaxy/jobs/metrics/instrumenters/__init__.pyi +++ /dev/null @@ -1,16 +0,0 @@ -# Stubs for galaxy.jobs.metrics.instrumenters (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from ...metrics import formatting as formatting - -INSTRUMENT_FILE_PREFIX = ... # type: str - -class InstrumentPlugin: - formatter = ... # type: Any - @property - def plugin_type(self): ... - def pre_execute_instrument(self, job_directory): ... - def post_execute_instrument(self, job_directory): ... - def job_properties(self, job_id, job_directory): ... diff --git a/typeshed/galaxy/jobs/metrics/instrumenters/collectl.pyi b/typeshed/galaxy/jobs/metrics/instrumenters/collectl.pyi deleted file mode 100644 index 080d2e5..0000000 --- a/typeshed/galaxy/jobs/metrics/instrumenters/collectl.pyi +++ /dev/null @@ -1,22 +0,0 @@ -# Stubs for galaxy.jobs.metrics.instrumenters.collectl (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -import formatting -from ..instrumenters import InstrumentPlugin - -class CollectlFormatter(formatting.JobMetricFormatter): - def format(self, key, value): ... - -class CollectlPlugin(InstrumentPlugin): - plugin_type = ... # type: str - formatter = ... # type: Any - saved_logs_path = ... # type: Any - summarize_process_data = ... # type: Any - log_collectl_program_output = ... # type: Any - process_statistics = ... # type: Any - def __init__(self, **kwargs) -> None: ... - def pre_execute_instrument(self, job_directory): ... - def post_execute_instrument(self, job_directory): ... - def job_properties(self, job_id, job_directory): ... diff --git a/typeshed/galaxy/jobs/metrics/instrumenters/core.pyi b/typeshed/galaxy/jobs/metrics/instrumenters/core.pyi deleted file mode 100644 index 885df5a..0000000 --- a/typeshed/galaxy/jobs/metrics/instrumenters/core.pyi +++ /dev/null @@ -1,18 +0,0 @@ -# Stubs for galaxy.jobs.metrics.instrumenters.core (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -import formatting -from ..instrumenters import InstrumentPlugin - -class CorePluginFormatter(formatting.JobMetricFormatter): - def format(self, key, value): ... - -class CorePlugin(InstrumentPlugin): - plugin_type = ... # type: str - formatter = ... # type: Any - def __init__(self, **kwargs) -> None: ... - def pre_execute_instrument(self, job_directory): ... - def post_execute_instrument(self, job_directory): ... - def job_properties(self, job_id, job_directory): ... diff --git a/typeshed/galaxy/jobs/metrics/instrumenters/cpuinfo.pyi b/typeshed/galaxy/jobs/metrics/instrumenters/cpuinfo.pyi deleted file mode 100644 index 00744ed..0000000 --- a/typeshed/galaxy/jobs/metrics/instrumenters/cpuinfo.pyi +++ /dev/null @@ -1,18 +0,0 @@ -# Stubs for galaxy.jobs.metrics.instrumenters.cpuinfo (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -import formatting -from ..instrumenters import InstrumentPlugin - -class CpuInfoFormatter(formatting.JobMetricFormatter): - def format(self, key, value): ... - -class CpuInfoPlugin(InstrumentPlugin): - plugin_type = ... # type: str - formatter = ... # type: Any - verbose = ... # type: Any - def __init__(self, **kwargs) -> None: ... - def pre_execute_instrument(self, job_directory): ... - def job_properties(self, job_id, job_directory): ... diff --git a/typeshed/galaxy/jobs/metrics/instrumenters/env.pyi b/typeshed/galaxy/jobs/metrics/instrumenters/env.pyi deleted file mode 100644 index 4113322..0000000 --- a/typeshed/galaxy/jobs/metrics/instrumenters/env.pyi +++ /dev/null @@ -1,18 +0,0 @@ -# Stubs for galaxy.jobs.metrics.instrumenters.env (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -import formatting -from ..instrumenters import InstrumentPlugin - -class EnvFormatter(formatting.JobMetricFormatter): ... - -class EnvPlugin(InstrumentPlugin): - plugin_type = ... # type: str - formatter = ... # type: Any - variables = ... # type: Any - def __init__(self, **kwargs) -> None: ... - def pre_execute_instrument(self, job_directory): ... - def post_execute_instrument(self, job_directory): ... - def job_properties(self, job_id, job_directory): ... diff --git a/typeshed/galaxy/jobs/metrics/instrumenters/meminfo.pyi b/typeshed/galaxy/jobs/metrics/instrumenters/meminfo.pyi deleted file mode 100644 index 344cfa8..0000000 --- a/typeshed/galaxy/jobs/metrics/instrumenters/meminfo.pyi +++ /dev/null @@ -1,18 +0,0 @@ -# Stubs for galaxy.jobs.metrics.instrumenters.meminfo (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -import formatting -from ..instrumenters import InstrumentPlugin - -class MemInfoFormatter(formatting.JobMetricFormatter): - def format(self, key, value): ... - -class MemInfoPlugin(InstrumentPlugin): - plugin_type = ... # type: str - formatter = ... # type: Any - verbose = ... # type: Any - def __init__(self, **kwargs) -> None: ... - def pre_execute_instrument(self, job_directory): ... - def job_properties(self, job_id, job_directory): ... diff --git a/typeshed/galaxy/jobs/metrics/instrumenters/uname.pyi b/typeshed/galaxy/jobs/metrics/instrumenters/uname.pyi deleted file mode 100644 index b541bd0..0000000 --- a/typeshed/galaxy/jobs/metrics/instrumenters/uname.pyi +++ /dev/null @@ -1,18 +0,0 @@ -# Stubs for galaxy.jobs.metrics.instrumenters.uname (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -import formatting -from ..instrumenters import InstrumentPlugin - -class UnameFormatter(formatting.JobMetricFormatter): - def format(self, key, value): ... - -class UnamePlugin(InstrumentPlugin): - plugin_type = ... # type: str - formatter = ... # type: Any - uname_args = ... # type: Any - def __init__(self, **kwargs) -> None: ... - def pre_execute_instrument(self, job_directory): ... - def job_properties(self, job_id, job_directory): ... diff --git a/typeshed/galaxy/objectstore/__init__.pyi b/typeshed/galaxy/objectstore/__init__.pyi deleted file mode 100644 index 82259bc..0000000 --- a/typeshed/galaxy/objectstore/__init__.pyi +++ /dev/null @@ -1,80 +0,0 @@ -# Stubs for galaxy.objectstore (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -object_session = ... # type: Any -NO_SESSION_ERROR_MESSAGE = ... # type: str -log = ... # type: Any - -class ObjectStore: - running = ... # type: bool - extra_dirs = ... # type: Any - config = ... # type: Any - check_old_style = ... # type: Any - def __init__(self, config, **kwargs) -> None: ... - def shutdown(self): ... - def exists(self, obj, base_dir: Optional[Any] = ..., dir_only: bool = ..., extra_dir: Optional[Any] = ..., extra_dir_at_root: bool = ..., alt_name: Optional[Any] = ...): ... - def file_ready(self, obj, base_dir: Optional[Any] = ..., dir_only: bool = ..., extra_dir: Optional[Any] = ..., extra_dir_at_root: bool = ..., alt_name: Optional[Any] = ..., obj_dir: bool = ...): ... - def create(self, obj, base_dir: Optional[Any] = ..., dir_only: bool = ..., extra_dir: Optional[Any] = ..., extra_dir_at_root: bool = ..., alt_name: Optional[Any] = ..., obj_dir: bool = ...): ... - def empty(self, obj, base_dir: Optional[Any] = ..., extra_dir: Optional[Any] = ..., extra_dir_at_root: bool = ..., alt_name: Optional[Any] = ..., obj_dir: bool = ...): ... - def size(self, obj, extra_dir: Optional[Any] = ..., extra_dir_at_root: bool = ..., alt_name: Optional[Any] = ..., obj_dir: bool = ...): ... - def delete(self, obj, entire_dir: bool = ..., base_dir: Optional[Any] = ..., extra_dir: Optional[Any] = ..., extra_dir_at_root: bool = ..., alt_name: Optional[Any] = ..., obj_dir: bool = ...): ... - def get_data(self, obj, start: int = ..., count: int = ..., base_dir: Optional[Any] = ..., extra_dir: Optional[Any] = ..., extra_dir_at_root: bool = ..., alt_name: Optional[Any] = ..., obj_dir: bool = ...): ... - def get_filename(self, obj, base_dir: Optional[Any] = ..., dir_only: bool = ..., extra_dir: Optional[Any] = ..., extra_dir_at_root: bool = ..., alt_name: Optional[Any] = ..., obj_dir: bool = ...): ... - def update_from_file(self, obj, base_dir: Optional[Any] = ..., extra_dir: Optional[Any] = ..., extra_dir_at_root: bool = ..., alt_name: Optional[Any] = ..., obj_dir: bool = ..., file_name: Optional[Any] = ..., create: bool = ...): ... - def get_object_url(https://github.com/self,%20obj,%20extra_dir:%20Optional[Any]%20=%20...,%20extra_dir_at_root:%20bool%20=%20...,%20alt_name:%20Optional[Any]%20=%20...,%20obj_dir:%20bool%20=%20...): ... - def get_store_usage_percent(self): ... - -class DiskObjectStore(ObjectStore): - file_path = ... # type: Any - def __init__(self, config, config_xml: Optional[Any] = ..., file_path: Optional[Any] = ..., extra_dirs: Optional[Any] = ...) -> None: ... - def exists(self, obj, **kwargs): ... - def create(self, obj, **kwargs): ... - def empty(self, obj, **kwargs): ... - def size(self, obj, **kwargs): ... - def delete(self, obj, entire_dir: bool = ..., **kwargs): ... - def get_data(self, obj, start: int = ..., count: int = ..., **kwargs): ... - def get_filename(self, obj, **kwargs): ... - def update_from_file(self, obj, file_name: Optional[Any] = ..., create: bool = ..., **kwargs): ... - def get_object_url(https://github.com/self,%20obj,%20**kwargs): ... - def get_store_usage_percent(self): ... - -class NestedObjectStore(ObjectStore): - backends = ... # type: Any - def __init__(self, config, config_xml: Optional[Any] = ...) -> None: ... - def shutdown(self): ... - def exists(self, obj, **kwargs): ... - def file_ready(self, obj, **kwargs): ... - def create(self, obj, **kwargs): ... - def empty(self, obj, **kwargs): ... - def size(self, obj, **kwargs): ... - def delete(self, obj, **kwargs): ... - def get_data(self, obj, **kwargs): ... - def get_filename(self, obj, **kwargs): ... - def update_from_file(self, obj, **kwargs): ... - def get_object_url(https://github.com/self,%20obj,%20**kwargs): ... - -class DistributedObjectStore(NestedObjectStore): - distributed_config = ... # type: Any - backends = ... # type: Any - weighted_backend_ids = ... # type: Any - original_weighted_backend_ids = ... # type: Any - max_percent_full = ... # type: Any - global_max_percent_full = ... # type: float - sleeper = ... # type: Any - filesystem_monitor_thread = ... # type: Any - def __init__(self, config, config_xml: Optional[Any] = ..., fsmon: bool = ...) -> None: ... - def shutdown(self): ... - def create(self, obj, **kwargs): ... - -class HierarchicalObjectStore(NestedObjectStore): - backends = ... # type: Any - def __init__(self, config, config_xml: Optional[Any] = ..., fsmon: bool = ...) -> None: ... - def exists(self, obj, **kwargs): ... - def create(self, obj, **kwargs): ... - -def build_object_store_from_config(config, fsmon: bool = ..., config_xml: Optional[Any] = ...): ... -def local_extra_dirs(func): ... -def convert_bytes(bytes): ... diff --git a/typeshed/galaxy/objectstore/azure_blob.pyi b/typeshed/galaxy/objectstore/azure_blob.pyi deleted file mode 100644 index 89b58c1..0000000 --- a/typeshed/galaxy/objectstore/azure_blob.pyi +++ /dev/null @@ -1,29 +0,0 @@ -# Stubs for galaxy.objectstore.azure_blob (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from ..objectstore import convert_bytes as convert_bytes, ObjectStore as ObjectStore - -BlockBlobService = ... # type: Any -NO_BLOBSERVICE_ERROR_MESSAGE = ... # type: str -log = ... # type: Any - -class AzureBlobObjectStore(ObjectStore): - staging_path = ... # type: Any - transfer_progress = ... # type: int - cache_size = ... # type: Any - sleeper = ... # type: Any - cache_monitor_thread = ... # type: Any - def __init__(self, config, config_xml) -> None: ... - def exists(self, obj, **kwargs): ... - def file_ready(self, obj, **kwargs): ... - def create(self, obj, **kwargs): ... - def empty(self, obj, **kwargs): ... - def size(self, obj, **kwargs): ... - def delete(self, obj, entire_dir: bool = ..., **kwargs): ... - def get_data(self, obj, start: int = ..., count: int = ..., **kwargs): ... - def get_filename(self, obj, **kwargs): ... - def update_from_file(self, obj, file_name: Optional[Any] = ..., create: bool = ..., **kwargs): ... - def get_object_url(https://github.com/self,%20obj,%20**kwargs): ... - def get_store_usage_percent(self): ... diff --git a/typeshed/galaxy/objectstore/pulsar.pyi b/typeshed/galaxy/objectstore/pulsar.pyi deleted file mode 100644 index bad1045..0000000 --- a/typeshed/galaxy/objectstore/pulsar.pyi +++ /dev/null @@ -1,24 +0,0 @@ -# Stubs for galaxy.objectstore.pulsar (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from ..objectstore import ObjectStore as ObjectStore - -ObjectStoreClientManager = ... # type: Any - -class PulsarObjectStore(ObjectStore): - pulsar_client = ... # type: Any - def __init__(self, config, config_xml) -> None: ... - def exists(self, obj, **kwds): ... - def file_ready(self, obj, **kwds): ... - def create(self, obj, **kwds): ... - def empty(self, obj, **kwds): ... - def size(self, obj, **kwds): ... - def delete(self, obj, **kwds): ... - def get_data(self, obj, **kwds): ... - def get_filename(self, obj, **kwds): ... - def update_from_file(self, obj, **kwds): ... - def get_store_usage_percent(self): ... - def get_object_url(https://github.com/self,%20obj,%20extra_dir:%20Optional[Any]%20=%20...,%20extra_dir_at_root:%20bool%20=%20...,%20alt_name:%20Optional[Any]%20=%20...): ... - def shutdown(self): ... diff --git a/typeshed/galaxy/objectstore/rods.pyi b/typeshed/galaxy/objectstore/rods.pyi deleted file mode 100644 index 125444b..0000000 --- a/typeshed/galaxy/objectstore/rods.pyi +++ /dev/null @@ -1,32 +0,0 @@ -# Stubs for galaxy.objectstore.rods (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from posixpath import basename as path_basename -from posixpath import dirname as path_dirname -from posixpath import join as path_join -from ..objectstore import DiskObjectStore as DiskObjectStore, local_extra_dirs as local_extra_dirs - -irods = ... # type: Any -IRODS_IMPORT_MESSAGE = ... # type: str -log = ... # type: Any - -class IRODSObjectStore(DiskObjectStore): - cache_path = ... # type: Any - default_resource = ... # type: Any - root_collection_path = ... # type: Any - root_collection = ... # type: Any - def __init__(self, config, file_path: Optional[Any] = ..., extra_dirs: Optional[Any] = ...) -> None: ... - def exists(self, obj, **kwargs): ... - def create(self, obj, **kwargs): ... - def empty(self, obj, **kwargs): ... - def size(self, obj, **kwargs): ... - def delete(self, obj, entire_dir: bool = ..., **kwargs): ... - def get_data(self, obj, start: int = ..., count: int = ..., **kwargs): ... - def get_filename(self, obj, **kwargs): ... - def update_from_file(self, obj, file_name: Optional[Any] = ..., create: bool = ..., **kwargs): ... - def get_object_url(https://github.com/self,%20obj,%20**kwargs): ... - def get_store_usage_percent(self): ... - -def rods_connect(): ... diff --git a/typeshed/galaxy/objectstore/s3.pyi b/typeshed/galaxy/objectstore/s3.pyi deleted file mode 100644 index 8ffbd92..0000000 --- a/typeshed/galaxy/objectstore/s3.pyi +++ /dev/null @@ -1,34 +0,0 @@ -# Stubs for galaxy.objectstore.s3 (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from .s3_multipart_upload import multipart_upload as multipart_upload -from ..objectstore import convert_bytes as convert_bytes, ObjectStore as ObjectStore - -boto = ... # type: Any -NO_BOTO_ERROR_MESSAGE = ... # type: str -log = ... # type: Any - -class S3ObjectStore(ObjectStore): - staging_path = ... # type: Any - transfer_progress = ... # type: int - bucket = ... # type: Any - cache_size = ... # type: Any - sleeper = ... # type: Any - cache_monitor_thread = ... # type: Any - use_axel = ... # type: bool - def __init__(self, config, config_xml) -> None: ... - def file_ready(self, obj, **kwargs): ... - def exists(self, obj, **kwargs): ... - def create(self, obj, **kwargs): ... - def empty(self, obj, **kwargs): ... - def size(self, obj, **kwargs): ... - def delete(self, obj, entire_dir: bool = ..., **kwargs): ... - def get_data(self, obj, start: int = ..., count: int = ..., **kwargs): ... - def get_filename(self, obj, **kwargs): ... - def update_from_file(self, obj, file_name: Optional[Any] = ..., create: bool = ..., **kwargs): ... - def get_object_url(https://github.com/self,%20obj,%20**kwargs): ... - def get_store_usage_percent(self): ... - -class SwiftObjectStore(S3ObjectStore): ... diff --git a/typeshed/galaxy/objectstore/s3_multipart_upload.pyi b/typeshed/galaxy/objectstore/s3_multipart_upload.pyi deleted file mode 100644 index 9bf1d87..0000000 --- a/typeshed/galaxy/objectstore/s3_multipart_upload.pyi +++ /dev/null @@ -1,13 +0,0 @@ -# Stubs for galaxy.objectstore.s3_multipart_upload (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -boto = ... # type: Any - -def map_wrap(f): ... -def mp_from_ids(s3server, mp_id, mp_keyname, mp_bucketname): ... -def transfer_part(s3server, mp_id, mp_keyname, mp_bucketname, i, part): ... -def multipart_upload(s3server, bucket, s3_key_name, tarball, mb_size): ... -def multimap(cores: Optional[Any] = ...): ... diff --git a/typeshed/galaxy/tools/__init__.pyi b/typeshed/galaxy/tools/__init__.pyi deleted file mode 100644 index ef883e9..0000000 --- a/typeshed/galaxy/tools/__init__.pyi +++ /dev/null @@ -1,4 +0,0 @@ -# Stubs for galaxy.tools (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - diff --git a/typeshed/galaxy/tools/cwl/__init__.pyi b/typeshed/galaxy/tools/cwl/__init__.pyi deleted file mode 100644 index 72bc049..0000000 --- a/typeshed/galaxy/tools/cwl/__init__.pyi +++ /dev/null @@ -1,8 +0,0 @@ -# Stubs for galaxy.tools.cwl (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from .cwltool_deps import needs_shell_quoting as needs_shell_quoting, shellescape as shellescape -from .parser import tool_proxy as tool_proxy, workflow_proxy as workflow_proxy -from .representation import to_cwl_job as to_cwl_job, to_galaxy_parameters as to_galaxy_parameters -from .runtime_actions import handle_outputs as handle_outputs diff --git a/typeshed/galaxy/tools/cwl/cwltool_deps.pyi b/typeshed/galaxy/tools/cwl/cwltool_deps.pyi deleted file mode 100644 index 351a420..0000000 --- a/typeshed/galaxy/tools/cwl/cwltool_deps.pyi +++ /dev/null @@ -1,22 +0,0 @@ -# Stubs for galaxy.tools.cwl.cwltool_deps (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from cwltool import main as main, workflow as workflow, process as process, pathmapper as pathmapper -from cwltool import load_tool as load_tool -import shellescape as shellescape -import schema_salad as schema_salad -from schema_salad import ref_resolver as ref_resolver - -main = ... # type: Any -workflow = ... # type: Any -process = ... # type: Any -pathmapper = ... # type: Any -load_tool = ... # type: Any -shellescape = ... # type: Any -schema_salad = ... # type: Any -ref_resolver = ... # type: Any -needs_shell_quoting = ... # type: Any - -def ensure_cwltool_available(): ... diff --git a/typeshed/galaxy/tools/cwl/parser.pyi b/typeshed/galaxy/tools/cwl/parser.pyi deleted file mode 100644 index 369b146..0000000 --- a/typeshed/galaxy/tools/cwl/parser.pyi +++ /dev/null @@ -1,94 +0,0 @@ -# Stubs for galaxy.tools.cwl.parser (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -def tool_proxy(tool_path, strict_cwl_validation: bool = ...): ... -def load_job_proxy(job_directory, strict_cwl_validation: bool = ...): ... - -class ToolProxy: - def __init__(self, tool, tool_path) -> None: ... - def job_proxy(self, input_dict, output_dict, job_directory: str = ...): ... - def input_instances(self): ... - def output_instances(self): ... - def docker_identifier(self): ... - def description(self): ... - def label(self): ... - -class CommandLineToolProxy(ToolProxy): - def description(self): ... - def label(self): ... - def input_instances(self): ... - def output_instances(self): ... - def docker_identifier(self): ... - -class ExpressionToolProxy(CommandLineToolProxy): ... - -class JobProxy: - def __init__(self, tool_proxy, input_dict, output_dict, job_directory) -> None: ... - def cwl_job(self): ... - @property - def is_command_line_job(self): ... - @property - def command_line(self): ... - @property - def stdin(self): ... - @property - def stdout(self): ... - @property - def environment(self): ... - @property - def generate_files(self): ... - def collect_outputs(self, tool_working_directory): ... - def save_job(self): ... - def output_id(self, output_name): ... - def output_path(self, output_name): ... - def output_secondary_files_dir(self, output_name, create: bool = ...): ... - def stage_files(self): ... - -class WorkflowProxy: - def __init__(self, workflow, workflow_path) -> None: ... - def step_proxies(self): ... - @property - def runnables(self): ... - def to_dict(self): ... - -class StepProxy: - def __init__(self, workflow_proxy, step) -> None: ... - def to_dict(self): ... - -class ConditionalInstance: - input_type = ... # type: Any - name = ... # type: Any - case = ... # type: Any - whens = ... # type: Any - def __init__(self, name, case, whens) -> None: ... - def to_dict(self): ... - -class SelectInputInstance: - input_type = ... # type: Any - name = ... # type: Any - label = ... # type: Any - description = ... # type: Any - options = ... # type: Any - def __init__(self, name, label, description, options) -> None: ... - def to_dict(self): ... - -class InputInstance: - input_type = ... # type: Any - name = ... # type: Any - label = ... # type: Any - description = ... # type: Any - required = ... # type: bool - array = ... # type: Any - area = ... # type: Any - def __init__(self, name, label, description, input_type, array: bool = ..., area: bool = ...) -> None: ... - def to_dict(self, itemwise: bool = ...): ... - -class OutputInstance: - name = ... # type: Any - output_data_type = ... # type: Any - output_type = ... # type: Any - path = ... # type: Any - def __init__(self, name, output_data_type, output_type, path: Optional[Any] = ...) -> None: ... diff --git a/typeshed/galaxy/tools/cwl/representation.pyi b/typeshed/galaxy/tools/cwl/representation.pyi deleted file mode 100644 index ef2cc45..0000000 --- a/typeshed/galaxy/tools/cwl/representation.pyi +++ /dev/null @@ -1,12 +0,0 @@ -# Stubs for galaxy.tools.cwl.representation (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -log = ... # type: Any -NOT_PRESENT = ... # type: Any -GALAXY_TO_CWL_TYPES = ... # type: Any - -def to_cwl_job(tool, param_dict, local_working_directory): ... -def to_galaxy_parameters(tool, as_dict): ... diff --git a/typeshed/galaxy/tools/cwl/runtime_actions.pyi b/typeshed/galaxy/tools/cwl/runtime_actions.pyi deleted file mode 100644 index 4f1558d..0000000 --- a/typeshed/galaxy/tools/cwl/runtime_actions.pyi +++ /dev/null @@ -1,7 +0,0 @@ -# Stubs for galaxy.tools.cwl.runtime_actions (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -def handle_outputs(job_directory: Optional[Any] = ...): ... diff --git a/typeshed/galaxy/tools/cwl/schema.pyi b/typeshed/galaxy/tools/cwl/schema.pyi deleted file mode 100644 index 1c51ead..0000000 --- a/typeshed/galaxy/tools/cwl/schema.pyi +++ /dev/null @@ -1,22 +0,0 @@ -# Stubs for galaxy.tools.cwl.schema (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from .cwltool_deps import ensure_cwltool_available as ensure_cwltool_available, load_tool as load_tool, schema_salad as schema_salad, workflow as workflow -from collections import namedtuple - -RawProcessReference = namedtuple('RawProcessReference', ['process_object', 'uri']) - -ProcessDefinition = namedtuple('ProcessDefinition', ['process_object', 'metadata', 'document_loader', 'avsc_names', 'raw_process_reference']) - -class SchemaLoader: - def __init__(self, strict: bool = ...) -> None: ... - @property - def raw_document_loader(self): ... - def raw_process_reference(self, path): ... - def process_definition(self, raw_reference): ... - def tool(self, **kwds): ... - -schema_loader = ... # type: Any -non_strict_schema_loader = ... # type: Any diff --git a/typeshed/galaxy/tools/deps/__init__.pyi b/typeshed/galaxy/tools/deps/__init__.pyi deleted file mode 100644 index 1df97ad..0000000 --- a/typeshed/galaxy/tools/deps/__init__.pyi +++ /dev/null @@ -1,41 +0,0 @@ -# Stubs for galaxy.tools.deps (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional, List -from .requirements import ToolRequirement as ToolRequirement, ToolRequirements as ToolRequirements -from .resolvers import NullDependency as NullDependency -from .resolvers.conda import CondaDependencyResolver as CondaDependencyResolver -from .resolvers.galaxy_packages import GalaxyPackageDependencyResolver as GalaxyPackageDependencyResolver -from .resolvers.tool_shed_packages import ToolShedPackageDependencyResolver as ToolShedPackageDependencyResolver - -log = ... # type: Any -CONFIG_VAL_NOT_FOUND = ... # type: Any - -def build_dependency_manager(config: Any) -> DependencyManager: ... - -class NullDependencyManager: - dependency_resolvers = ... # type: Any - def uses_tool_shed_dependencies(self): ... - def dependency_shell_commands(self, requirements: ToolRequirements, **kwds) -> List[str]: ... - def find_dep(self, name, version: Optional[Any] = ..., type: str = ..., **kwds): ... - -class DependencyManager: - default_base_path = ... # type: Any - resolver_classes = ... # type: Any - dependency_resolvers = ... # type: Any - def __init__(self, default_base_path, conf_file: Optional[Any] = ..., app_config: Any = ...) -> None: ... - def get_resolver_option(self, resolver, key, explicit_resolver_options: Any = ...): ... - def get_app_option(self, key, default: Optional[Any] = ...): ... - def dependency_shell_commands(self, requirements: ToolRequirements, **kwds) -> List[str]: ... - def requirements_to_dependencies(self, requirements, **kwds): ... - def uses_tool_shed_dependencies(self): ... - def find_dep(self, name, version: Optional[Any] = ..., type: str = ..., **kwds): ... - -class CachedDependencyManager(DependencyManager): - tool_dependency_cache_dir = ... # type: Any - def __init__(self, default_base_path, conf_file: Optional[Any] = ..., app_config: Any = ..., tool_dependency_cache_dir: Optional[Any] = ...) -> None: ... - def build_cache(self, requirements, **kwds): ... - def dependency_shell_commands(self, requirements: ToolRequirements, **kwds) -> List[str]: ... - def hash_dependencies(self, resolved_dependencies): ... - def get_hashed_dependencies_path(self, resolved_dependencies): ... diff --git a/typeshed/galaxy/tools/deps/brew_exts.pyi b/typeshed/galaxy/tools/deps/brew_exts.pyi deleted file mode 100644 index c526375..0000000 --- a/typeshed/galaxy/tools/deps/brew_exts.pyi +++ /dev/null @@ -1,74 +0,0 @@ -# Stubs for galaxy.tools.deps.brew_exts (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -WHITESPACE_PATTERN = ... # type: Any -DESCRIPTION = ... # type: str -DEFAULT_HOMEBREW_ROOT = ... # type: str -NO_BREW_ERROR_MESSAGE = ... # type: str -CANNOT_DETERMINE_TAP_ERROR_MESSAGE = ... # type: str -VERBOSE = ... # type: bool -RELAXED = ... # type: bool -BREW_ARGS = ... # type: Any - -class BrewContext: - homebrew_prefix = ... # type: Any - homebrew_cellar = ... # type: Any - def __init__(self, args: Optional[Any] = ...) -> None: ... - -class RecipeContext: - @staticmethod - def from_args(args, brew_context: Optional[Any] = ...): ... - recipe = ... # type: Any - version = ... # type: Any - brew_context = ... # type: Any - def __init__(self, recipe, version, brew_context: Optional[Any] = ...) -> None: ... - @property - def cellar_path(self): ... - @property - def tap_path(self): ... - -def main(): ... - -class CommandLineException(Exception): - command = ... # type: Any - stdout = ... # type: Any - stderr = ... # type: Any - message = ... # type: Any - def __init__(self, command, stdout, stderr) -> None: ... - -def versioned_install(recipe_context, package: Optional[Any] = ..., version: Optional[Any] = ..., installed_deps: Any = ...): ... -def commit_for_version(recipe_context, package, version): ... -def print_versioned_deps(recipe_context, recipe, version): ... -def load_versioned_deps(cellar_path, relaxed: Optional[Any] = ...): ... -def unversioned_install(package): ... -def attempt_unlink_all(package, deps): ... -def attempt_unlink(package): ... -def brew_execute(args, env: Optional[Any] = ...): ... -def build_env_statements_from_recipe_context(recipe_context, **kwds): ... -def build_env_statements(cellar_root, cellar_path, relaxed: Optional[Any] = ..., custom_only: bool = ...): ... -def build_env_actions(deps, cellar_root, cellar_path, relaxed: Optional[Any] = ..., custom_only: bool = ...): ... - -class EnvAction: - variable = ... # type: Any - action = ... # type: Any - value = ... # type: Any - def __init__(self, keg_root, action_description) -> None: ... - @staticmethod - def build_env(env_actions): ... - def modify_environ(self, environ): ... - def to_statements(self): ... - -def brew_head_at_version(recipe_context, package, version): ... -def brew_head_at_commit(commit, tap_path): ... -def git_execute(args): ... -def execute(cmds, env: Optional[Any] = ...): ... -def brew_deps(package): ... -def brew_info(recipe): ... -def extended_brew_info(recipe): ... -def brew_versions_info(package, tap_path): ... -def recipe_cellar_path(cellar_path, recipe, version): ... -def ensure_brew_on_path(args): ... -def which(file): ... diff --git a/typeshed/galaxy/tools/deps/brew_util.pyi b/typeshed/galaxy/tools/deps/brew_util.pyi deleted file mode 100644 index c791f18..0000000 --- a/typeshed/galaxy/tools/deps/brew_util.pyi +++ /dev/null @@ -1,18 +0,0 @@ -# Stubs for galaxy.tools.deps.brew_util (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from ..deps import brew_exts as brew_exts - -DEFAULT_TAP = ... # type: str - -class HomebrewRecipe: - recipe = ... # type: Any - version = ... # type: Any - tap = ... # type: Any - def __init__(self, recipe, version, tap) -> None: ... - -def requirements_to_recipes(requirements): ... -def requirement_to_recipe(requirement): ... -def requirements_to_recipe_contexts(requirements, brew_context): ... diff --git a/typeshed/galaxy/tools/deps/commands.pyi b/typeshed/galaxy/tools/deps/commands.pyi deleted file mode 100644 index a11b90d..0000000 --- a/typeshed/galaxy/tools/deps/commands.pyi +++ /dev/null @@ -1,22 +0,0 @@ -# Stubs for galaxy.tools.deps.commands (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from galaxy.util import which as which - -def redirecting_io(sys: Any = ...): ... -def redirect_aware_commmunicate(p, sys: Any = ...): ... -def shell(cmds, env: Optional[Any] = ..., **kwds): ... -def shell_process(cmds, env: Optional[Any] = ..., **kwds): ... -def execute(cmds): ... -def argv_to_str(command_argv, quote: bool = ...): ... -def download_command(url, to: Any = ..., quote_url: bool = ...): ... - -class CommandLineException(Exception): - command = ... # type: Any - stdout = ... # type: Any - stderr = ... # type: Any - returncode = ... # type: Any - message = ... # type: Any - def __init__(self, command, stdout, stderr, returncode) -> None: ... diff --git a/typeshed/galaxy/tools/deps/conda_compat.pyi b/typeshed/galaxy/tools/deps/conda_compat.pyi deleted file mode 100644 index 0cc6382..0000000 --- a/typeshed/galaxy/tools/deps/conda_compat.pyi +++ /dev/null @@ -1,21 +0,0 @@ -# Stubs for galaxy.tools.deps.conda_compat (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from conda_build.metadata import MetaData as MetaData - -MetaData = ... # type: Any - -class _Memoized: - func = ... # type: Any - cache = ... # type: Any - def __init__(self, func) -> None: ... - def __call__(self, *args): ... - -def raw_metadata(recipe_dir): ... - -class _MetaData: - meta = ... # type: Any - def __init__(self, input_dir) -> None: ... - def get_value(self, field, default: Optional[Any] = ...): ... diff --git a/typeshed/galaxy/tools/deps/conda_util.pyi b/typeshed/galaxy/tools/deps/conda_util.pyi deleted file mode 100644 index 1e418ba..0000000 --- a/typeshed/galaxy/tools/deps/conda_util.pyi +++ /dev/null @@ -1,69 +0,0 @@ -# Stubs for galaxy.tools.deps.conda_util (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -import installable -from sys import platform as _platform - -class CondaContext(installable.InstallableContext): - installable_description = ... # type: str - condarc_override = ... # type: Any - conda_exec = ... # type: Any - debug = ... # type: Any - shell_exec = ... # type: Any - copy_dependencies = ... # type: Any - conda_prefix = ... # type: Any - ensure_channels = ... # type: Any - ensured_channels = ... # type: bool - use_local = ... # type: Any - def __init__(self, conda_prefix: Optional[Any] = ..., conda_exec: Optional[Any] = ..., shell_exec: Optional[Any] = ..., debug: bool = ..., ensure_channels: str = ..., condarc_override: Optional[Any] = ..., use_path_exec: Any = ..., copy_dependencies: bool = ..., use_local: Any = ...) -> None: ... - @property - def conda_version(self): ... - @property - def conda_build_available(self): ... - def ensure_channels_configured(self): ... - def ensure_conda_build_installed_if_needed(self): ... - def conda_info(self): ... - def is_conda_installed(self): ... - def can_install_conda(self): ... - def load_condarc(self): ... - def save_condarc(self, conf): ... - @property - def condarc(self): ... - def command(self, operation, args): ... - def exec_command(self, operation, args): ... - def exec_create(self, args, allow_local: bool = ...): ... - def exec_remove(self, args): ... - def exec_install(self, args, allow_local: bool = ...): ... - def exec_clean(self, args: Any = ..., quiet: bool = ...): ... - def export_list(self, name, path): ... - def env_path(self, env_name): ... - @property - def envs_path(self): ... - def has_env(self, env_name): ... - @property - def deactivate(self): ... - @property - def activate(self): ... - def is_installed(self): ... - def can_install(self): ... - @property - def parent_path(self): ... - -class CondaTarget: - package = ... # type: Any - version = ... # type: Any - channel = ... # type: Any - def __init__(self, package, version: Optional[Any] = ..., channel: Optional[Any] = ...) -> None: ... - @property - def package_specifier(self): ... - @property - def install_environment(self): ... - def __hash__(self): ... - def __eq__(self, other): ... - def __ne__(self, other): ... - -def install_conda(conda_context: Optional[Any] = ..., force_conda_build: bool = ...): ... -def install_conda_target(conda_target, conda_context: Optional[Any] = ..., skip_environment: bool = ...): ... -def requirements_to_conda_targets(requirements, conda_context: Optional[Any] = ...): ... diff --git a/typeshed/galaxy/tools/deps/container_resolvers/__init__.pyi b/typeshed/galaxy/tools/deps/container_resolvers/__init__.pyi deleted file mode 100644 index 4e8c822..0000000 --- a/typeshed/galaxy/tools/deps/container_resolvers/__init__.pyi +++ /dev/null @@ -1,14 +0,0 @@ -# Stubs for galaxy.tools.deps.container_resolvers (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from galaxy.util.dictifiable import Dictifiable - -class ContainerResolver(Dictifiable): - dict_collection_visible_keys = ... # type: Any - app_info = ... # type: Any - resolver_kwds = ... # type: Any - def __init__(self, app_info: Optional[Any] = ..., **kwds) -> None: ... - def resolve(self, tool_info): ... - def resolver_type(self): ... diff --git a/typeshed/galaxy/tools/deps/container_resolvers/explicit.pyi b/typeshed/galaxy/tools/deps/container_resolvers/explicit.pyi deleted file mode 100644 index 3f45f95..0000000 --- a/typeshed/galaxy/tools/deps/container_resolvers/explicit.pyi +++ /dev/null @@ -1,9 +0,0 @@ -# Stubs for galaxy.tools.deps.container_resolvers.explicit (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from ..container_resolvers import ContainerResolver - -class ExplicitContainerResolver(ContainerResolver): - resolver_type = ... # type: str - def resolve(self, enabled_container_types, tool_info): ... diff --git a/typeshed/galaxy/tools/deps/container_resolvers/mulled.pyi b/typeshed/galaxy/tools/deps/container_resolvers/mulled.pyi deleted file mode 100644 index 5f7a6b4..0000000 --- a/typeshed/galaxy/tools/deps/container_resolvers/mulled.pyi +++ /dev/null @@ -1,55 +0,0 @@ -# Stubs for galaxy.tools.deps.container_resolvers.mulled (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from ..container_resolvers import ContainerResolver -from collections import namedtuple - -CachedMulledImageSingleTarget = namedtuple('CachedMulledImageSingleTarget', ['package_name', 'version', 'build', 'image_identifier']) - -CachedV1MulledImageMultiTarget = namedtuple('CachedV1MulledImageMultiTarget', ['hash', 'build', 'image_identifier']) - -CachedV2MulledImageMultiTarget = namedtuple('CachedV2MulledImageMultiTarget', ['package_hash', 'version_hash', 'build', 'image_identifier']) - -class CachedMulledDockerContainerResolver(ContainerResolver): - resolver_type = ... # type: str - container_type = ... # type: str - namespace = ... # type: Any - hash_func = ... # type: Any - def __init__(self, app_info: Optional[Any] = ..., namespace: Optional[Any] = ..., hash_func: str = ...) -> None: ... - def resolve(self, enabled_container_types, tool_info): ... - -class CachedMulledSingularityContainerResolver(ContainerResolver): - resolver_type = ... # type: str - container_type = ... # type: str - cache_directory = ... # type: Any - hash_func = ... # type: Any - def __init__(self, app_info: Optional[Any] = ..., hash_func: str = ...) -> None: ... - def resolve(self, enabled_container_types, tool_info): ... - -class MulledDockerContainerResolver(ContainerResolver): - resolver_type = ... # type: str - container_type = ... # type: str - namespace = ... # type: Any - hash_func = ... # type: Any - def __init__(self, app_info: Optional[Any] = ..., namespace: str = ..., hash_func: str = ...) -> None: ... - def resolve(self, enabled_container_types, tool_info): ... - -class BuildMulledDockerContainerResolver(ContainerResolver): - resolver_type = ... # type: str - container_type = ... # type: str - namespace = ... # type: Any - hash_func = ... # type: Any - auto_init = ... # type: Any - def __init__(self, app_info: Optional[Any] = ..., namespace: str = ..., hash_func: str = ..., **kwds) -> None: ... - def resolve(self, enabled_container_types, tool_info): ... - -class BuildMulledSingularityContainerResolver(ContainerResolver): - resolver_type = ... # type: str - container_type = ... # type: str - cache_directory = ... # type: Any - hash_func = ... # type: Any - auto_init = ... # type: Any - def __init__(self, app_info: Optional[Any] = ..., hash_func: str = ..., **kwds) -> None: ... - def resolve(self, enabled_container_types, tool_info): ... diff --git a/typeshed/galaxy/tools/deps/containers.pyi b/typeshed/galaxy/tools/deps/containers.pyi deleted file mode 100644 index 5a18a63..0000000 --- a/typeshed/galaxy/tools/deps/containers.pyi +++ /dev/null @@ -1,99 +0,0 @@ -# Stubs for galaxy.tools.deps.containers (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from .container_resolvers.explicit import ExplicitContainerResolver as ExplicitContainerResolver -from .container_resolvers.mulled import BuildMulledDockerContainerResolver as BuildMulledDockerContainerResolver, BuildMulledSingularityContainerResolver as BuildMulledSingularityContainerResolver, CachedMulledDockerContainerResolver as CachedMulledDockerContainerResolver, CachedMulledSingularityContainerResolver as CachedMulledSingularityContainerResolver, MulledDockerContainerResolver as MulledDockerContainerResolver -from .requirements import ContainerDescription as ContainerDescription -from .requirements import DEFAULT_CONTAINER_RESOLVE_DEPENDENCIES as DEFAULT_CONTAINER_RESOLVE_DEPENDENCIES, DEFAULT_CONTAINER_SHELL as DEFAULT_CONTAINER_SHELL -from ..deps import docker_util as docker_util -from ..deps import singularity_util as singularity_util - -log = ... # type: Any -DOCKER_CONTAINER_TYPE = ... # type: str -SINGULARITY_CONTAINER_TYPE = ... # type: str -DEFAULT_CONTAINER_TYPE = ... # type: Any -ALL_CONTAINER_TYPES = ... # type: Any -LOAD_CACHED_IMAGE_COMMAND_TEMPLATE = ... # type: str - -class ContainerFinder: - app_info = ... # type: Any - container_registry = ... # type: Any - def __init__(self, app_info) -> None: ... - def find_best_container_description(self, enabled_container_types, tool_info): ... - def find_container(self, tool_info, destination_info, job_info): ... - -class NullContainerFinder: - def find_container(self, tool_info, destination_info, job_info): ... - -class ContainerRegistry: - resolver_classes = ... # type: Any - enable_beta_mulled_containers = ... # type: Any - app_info = ... # type: Any - container_resolvers = ... # type: Any - def __init__(self, app_info) -> None: ... - def find_best_container_description(self, enabled_container_types, tool_info): ... - -class AppInfo: - galaxy_root_dir = ... # type: Any - default_file_path = ... # type: Any - outputs_to_working_directory = ... # type: Any - container_image_cache_path = ... # type: Any - library_import_dir = ... # type: Any - enable_beta_mulled_containers = ... # type: Any - containers_resolvers_config_file = ... # type: Any - involucro_path = ... # type: Any - involucro_auto_init = ... # type: Any - def __init__(self, galaxy_root_dir: Optional[Any] = ..., default_file_path: Optional[Any] = ..., outputs_to_working_directory: bool = ..., container_image_cache_path: Optional[Any] = ..., library_import_dir: Optional[Any] = ..., enable_beta_mulled_containers: bool = ..., containers_resolvers_config_file: Optional[Any] = ..., involucro_path: Optional[Any] = ..., involucro_auto_init: bool = ...) -> None: ... - -class ToolInfo: - container_descriptions = ... # type: Any - requirements = ... # type: Any - requires_galaxy_python_environment = ... # type: Any - env_pass_through = ... # type: Any - def __init__(self, container_descriptions: Any = ..., requirements: Any = ..., requires_galaxy_python_environment: bool = ...) -> None: ... - -class JobInfo: - working_directory = ... # type: Any - job_directory = ... # type: Any - tool_directory = ... # type: Any - job_directory_type = ... # type: Any - def __init__(self, working_directory, tool_directory, job_directory, job_directory_type) -> None: ... - -class Container: - container_id = ... # type: Any - app_info = ... # type: Any - tool_info = ... # type: Any - destination_info = ... # type: Any - job_info = ... # type: Any - container_description = ... # type: Any - def __init__(self, container_id, app_info, tool_info, destination_info, job_info, container_description) -> None: ... - @property - def resolve_dependencies(self): ... - @property - def shell(self): ... - def containerize_command(self, command): ... - -def preprocess_volumes(volumes_raw_str, container_type): ... - -class HasDockerLikeVolumes: ... - -class DockerContainer(Container, HasDockerLikeVolumes): - container_type = ... # type: Any - def containerize_command(self, command): ... - -def docker_cache_path(cache_directory, container_id): ... - -class SingularityContainer(Container, HasDockerLikeVolumes): - container_type = ... # type: Any - def containerize_command(self, command): ... - -CONTAINER_CLASSES = ... # type: Any - -class NullContainer: - def __init__(self) -> None: ... - def __bool__(self): ... - __nonzero__ = ... # type: Any - -NULL_CONTAINER = ... # type: Any diff --git a/typeshed/galaxy/tools/deps/dependencies.pyi b/typeshed/galaxy/tools/deps/dependencies.pyi deleted file mode 100644 index 04907fe..0000000 --- a/typeshed/galaxy/tools/deps/dependencies.pyi +++ /dev/null @@ -1,13 +0,0 @@ -# Stubs for galaxy.tools.deps.dependencies (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -class DependenciesDescription: - requirements = ... # type: Any - installed_tool_dependencies = ... # type: Any - def __init__(self, requirements: Any = ..., installed_tool_dependencies: Any = ...) -> None: ... - def to_dict(self): ... - @staticmethod - def from_dict(as_dict): ... diff --git a/typeshed/galaxy/tools/deps/docker_util.pyi b/typeshed/galaxy/tools/deps/docker_util.pyi deleted file mode 100644 index e98b338..0000000 --- a/typeshed/galaxy/tools/deps/docker_util.pyi +++ /dev/null @@ -1,41 +0,0 @@ -# Stubs for galaxy.tools.deps.docker_util (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from .commands import argv_to_str as argv_to_str - -DEFAULT_DOCKER_COMMAND = ... # type: str -DEFAULT_SUDO = ... # type: bool -DEFAULT_SUDO_COMMAND = ... # type: str -DEFAULT_HOST = ... # type: Any -DEFAULT_VOLUME_MOUNT_TYPE = ... # type: str -DEFAULT_WORKING_DIRECTORY = ... # type: Any -DEFAULT_NET = ... # type: Any -DEFAULT_MEMORY = ... # type: Any -DEFAULT_VOLUMES_FROM = ... # type: Any -DEFAULT_AUTO_REMOVE = ... # type: bool -DEFAULT_SET_USER = ... # type: str -DEFAULT_RUN_EXTRA_ARGUMENTS = ... # type: Any - -class DockerVolume: - from_path = ... # type: Any - to_path = ... # type: Any - how = ... # type: Any - def __init__(self, path, to_path: Optional[Any] = ..., how: Any = ...) -> None: ... - @staticmethod - def volumes_from_str(volumes_as_str): ... - @staticmethod - def volume_from_str(as_str): ... - -def kill_command(container, signal: Optional[Any] = ..., **kwds): ... -def logs_command(container, **kwds): ... -def build_command(image, docker_build_path, **kwds): ... -def build_save_image_command(image, destination, **kwds): ... -def build_pull_command(tag, **kwds): ... -def build_docker_cache_command(image, **kwds): ... -def build_docker_images_command(truncate: bool = ..., **kwds): ... -def build_docker_load_command(**kwds): ... -def build_docker_run_command(container_command, image, interactive: bool = ..., terminal: bool = ..., tag: Optional[Any] = ..., volumes: Any = ..., volumes_from: Any = ..., memory: Any = ..., env_directives: Any = ..., working_directory: Any = ..., name: Optional[Any] = ..., net: Any = ..., run_extra_arguments: Any = ..., docker_cmd: Any = ..., sudo: Any = ..., sudo_cmd: Any = ..., auto_rm: Any = ..., set_user: Any = ..., host: Any = ...): ... -def command_list(command, command_args: Any = ..., **kwds): ... -def command_shell(command, command_args: Any = ..., **kwds): ... diff --git a/typeshed/galaxy/tools/deps/dockerfiles.pyi b/typeshed/galaxy/tools/deps/dockerfiles.pyi deleted file mode 100644 index 3cf02d5..0000000 --- a/typeshed/galaxy/tools/deps/dockerfiles.pyi +++ /dev/null @@ -1,15 +0,0 @@ -# Stubs for galaxy.tools.deps.dockerfiles (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from ..deps import commands as commands -from ..deps import docker_util as docker_util -from ..deps.containers import docker_cache_path as docker_cache_path -from ..deps.requirements import parse_requirements_from_xml as parse_requirements_from_xml -from ...tools import loader_directory as loader_directory - -log = ... # type: Any - -def docker_host_args(**kwds): ... -def dockerfile_build(path, dockerfile: Optional[Any] = ..., error: Any = ..., **kwds): ... diff --git a/typeshed/galaxy/tools/deps/installable.pyi b/typeshed/galaxy/tools/deps/installable.pyi deleted file mode 100644 index 818eaa2..0000000 --- a/typeshed/galaxy/tools/deps/installable.pyi +++ /dev/null @@ -1,15 +0,0 @@ -# Stubs for galaxy.tools.deps.installable (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -log = ... # type: Any - -class InstallableContext: - def is_installed(self): ... - def can_install(self): ... - def installable_description(self): ... - def parent_path(self): ... - -def ensure_installed(installable_context, install_func, auto_init): ... diff --git a/typeshed/galaxy/tools/deps/mulled/__init__.pyi b/typeshed/galaxy/tools/deps/mulled/__init__.pyi deleted file mode 100644 index a3f6bf3..0000000 --- a/typeshed/galaxy/tools/deps/mulled/__init__.pyi +++ /dev/null @@ -1,4 +0,0 @@ -# Stubs for galaxy.tools.deps.mulled (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - diff --git a/typeshed/galaxy/tools/deps/mulled/_cli.pyi b/typeshed/galaxy/tools/deps/mulled/_cli.pyi deleted file mode 100644 index db35991..0000000 --- a/typeshed/galaxy/tools/deps/mulled/_cli.pyi +++ /dev/null @@ -1,5 +0,0 @@ -# Stubs for galaxy.tools.deps.mulled._cli (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -def arg_parser(argv, globals): ... diff --git a/typeshed/galaxy/tools/deps/mulled/mulled_build.pyi b/typeshed/galaxy/tools/deps/mulled/mulled_build.pyi deleted file mode 100644 index 2565050..0000000 --- a/typeshed/galaxy/tools/deps/mulled/mulled_build.pyi +++ /dev/null @@ -1,24 +0,0 @@ -# Stubs for galaxy.tools.deps.mulled.mulled_build (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -import installable -from sys import platform as _platform - -class BuildExistsException(Exception): ... - -class InvolucroContext(installable.InstallableContext): - installable_description = ... # type: str - involucro_bin = ... # type: str - shell_exec = ... # type: Any - verbose = ... # type: Any - def __init__(self, involucro_bin: Optional[Any] = ..., shell_exec: Optional[Any] = ..., verbose: str = ...) -> None: ... - def build_command(self, involucro_args): ... - def exec_command(self, involucro_args): ... - def is_installed(self): ... - def can_install(self): ... - @property - def parent_path(self): ... - -def main(argv: Optional[Any] = ...): ... diff --git a/typeshed/galaxy/tools/deps/mulled/mulled_build_channel.pyi b/typeshed/galaxy/tools/deps/mulled/mulled_build_channel.pyi deleted file mode 100644 index c0039bf..0000000 --- a/typeshed/galaxy/tools/deps/mulled/mulled_build_channel.pyi +++ /dev/null @@ -1,7 +0,0 @@ -# Stubs for galaxy.tools.deps.mulled.mulled_build_channel (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -def main(argv: Optional[Any] = ...): ... diff --git a/typeshed/galaxy/tools/deps/mulled/mulled_build_files.pyi b/typeshed/galaxy/tools/deps/mulled/mulled_build_files.pyi deleted file mode 100644 index 0057d4d..0000000 --- a/typeshed/galaxy/tools/deps/mulled/mulled_build_files.pyi +++ /dev/null @@ -1,10 +0,0 @@ -# Stubs for galaxy.tools.deps.mulled.mulled_build_files (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from collections import namedtuple - -def main(argv: Optional[Any] = ...): ... - -_Line = namedtuple('_Line', ['targets', 'image_build', 'name_override']) diff --git a/typeshed/galaxy/tools/deps/mulled/mulled_build_tool.pyi b/typeshed/galaxy/tools/deps/mulled/mulled_build_tool.pyi deleted file mode 100644 index e4af0da..0000000 --- a/typeshed/galaxy/tools/deps/mulled/mulled_build_tool.pyi +++ /dev/null @@ -1,8 +0,0 @@ -# Stubs for galaxy.tools.deps.mulled.mulled_build_tool (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -def main(argv: Optional[Any] = ...): ... -def requirements_to_mulled_targets(requirements): ... diff --git a/typeshed/galaxy/tools/deps/mulled/mulled_search.pyi b/typeshed/galaxy/tools/deps/mulled/mulled_search.pyi deleted file mode 100644 index 9c8e9c2..0000000 --- a/typeshed/galaxy/tools/deps/mulled/mulled_search.pyi +++ /dev/null @@ -1,23 +0,0 @@ -# Stubs for galaxy.tools.deps.mulled.mulled_search (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -requests = ... # type: Any -Schema = ... # type: Any -TEXT = ... # type: Any -STORED = ... # type: Any -create_in = ... # type: Any -QueryParser = ... # type: Any -QUAY_API_URL = ... # type: str - -class QuaySearch: - index = ... # type: Any - organization = ... # type: Any - def __init__(self, organization) -> None: ... - def build_index(self): ... - def search_repository(self, search_string, non_strict): ... - def get_additional_repository_information(self, repository_string): ... - -def main(argv: Optional[Any] = ...): ... diff --git a/typeshed/galaxy/tools/deps/mulled/util.pyi b/typeshed/galaxy/tools/deps/mulled/util.pyi deleted file mode 100644 index 33063c2..0000000 --- a/typeshed/galaxy/tools/deps/mulled/util.pyi +++ /dev/null @@ -1,23 +0,0 @@ -# Stubs for galaxy.tools.deps.mulled.util (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from collections import namedtuple - -def quay_versions(namespace, pkg_name): ... -def mulled_tags_for(namespace, image, tag_prefix: Optional[Any] = ...): ... -def split_tag(tag): ... -def version_sorted(elements): ... - -Target = namedtuple('Target', ['package_name', 'version', 'build']) - -def build_target(package_name, version: Optional[Any] = ..., build: Optional[Any] = ..., tag: Optional[Any] = ...): ... -def conda_build_target_str(target): ... -def v1_image_name(targets, image_build: Optional[Any] = ..., name_override: Optional[Any] = ...): ... -def v2_image_name(targets, image_build: Optional[Any] = ..., name_override: Optional[Any] = ...): ... - -image_name = ... # type: Any - -# Names in __all__ with no definition: -# Target diff --git a/typeshed/galaxy/tools/deps/requirements.pyi b/typeshed/galaxy/tools/deps/requirements.pyi deleted file mode 100644 index 9cb78c3..0000000 --- a/typeshed/galaxy/tools/deps/requirements.pyi +++ /dev/null @@ -1,75 +0,0 @@ -# Stubs for galaxy.tools.deps.requirements (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Dict, List, Optional - -DEFAULT_REQUIREMENT_TYPE = ... # type: str -DEFAULT_REQUIREMENT_VERSION = ... # type: Any - -class ToolRequirement: - name = ... # type: Any - type = ... # type: Any - version = ... # type: Any - specs = ... # type: Any - def __init__(self, name: Optional[Any] = ..., type: Optional[Any] = ..., version: Optional[Any] = ..., specs: Any = ...) -> None: ... - def to_dict(self) -> Dict[str, Any]: ... - def copy(self): ... - @staticmethod - def from_dict(dict: Dict[str, Any]) -> ToolRequirement: ... - def __eq__(self, other): ... - def __ne__(self, other): ... - def __hash__(self): ... - -class RequirementSpecification: - uri = ... # type: Any - version = ... # type: Any - def __init__(self, uri, version: Optional[Any] = ...) -> None: ... - @property - def specifies_version(self): ... - @property - def short_name(self): ... - def to_dict(self): ... - @staticmethod - def from_dict(dict: Dict[str, Any]) -> ToolRequirements: ... - def __eq__(self, other): ... - def __ne__(self, other): ... - def __hash__(self): ... - -class ToolRequirements: - tool_requirements = ... # type: Any - def __init__(self, tool_requirements: Optional[Any] = ...) -> None: ... - @staticmethod - def from_list(requirements: List[ToolRequirement]) -> ToolRequirements: ... - @property - def resolvable(self): ... - @property - def packages(self): ... - def to_list(self) -> List[ToolRequirement]: ... - def append(self, requirement): ... - def __eq__(self, other): ... - def __ne__(self, other): ... - def __iter__(self): ... - def __getitem__(self, ii): ... - def __len__(self): ... - def __hash__(self): ... - -class ToolRequirementsException(Exception): ... - -DEFAULT_CONTAINER_TYPE = ... # type: str -DEFAULT_CONTAINER_RESOLVE_DEPENDENCIES = ... # type: bool -DEFAULT_CONTAINER_SHELL = ... # type: str - -class ContainerDescription: - identifier = ... # type: Any - type = ... # type: Any - resolve_dependencies = ... # type: Any - shell = ... # type: Any - def __init__(self, identifier: Optional[Any] = ..., type: Any = ..., resolve_dependencies: Any = ..., shell: Any = ...) -> None: ... - def to_dict(self): ... - @staticmethod - def from_dict(dict): ... - -def parse_requirements_from_dict(root_dict): ... -def parse_requirements_from_xml(xml_root): ... -def container_from_element(container_elem): ... diff --git a/typeshed/galaxy/tools/deps/resolvers/__init__.pyi b/typeshed/galaxy/tools/deps/resolvers/__init__.pyi deleted file mode 100644 index a1ffb20..0000000 --- a/typeshed/galaxy/tools/deps/resolvers/__init__.pyi +++ /dev/null @@ -1,62 +0,0 @@ -# Stubs for galaxy.tools.deps.resolvers (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from galaxy.util.dictifiable import Dictifiable -from ..requirements import ToolRequirement as ToolRequirement - -class DependencyResolver(Dictifiable): - dict_collection_visible_keys = ... # type: Any - disabled = ... # type: bool - resolves_simple_dependencies = ... # type: bool - can_uninstall_dependencies = ... # type: bool - config_options = ... # type: Any - def resolve(self, requirement, **kwds): ... - -class MultipleDependencyResolver: - def resolve_all(self, requirements, **kwds): ... - -class ListableDependencyResolver: - def list_dependencies(self): ... - -class MappableDependencyResolver: ... - -FROM_UNVERSIONED = ... # type: Any - -class RequirementMapping: - from_name = ... # type: Any - from_version = ... # type: Any - to_name = ... # type: Any - to_version = ... # type: Any - def __init__(self, from_name, from_version, to_name, to_version) -> None: ... - def matches_requirement(self, requirement): ... - def apply(self, requirement): ... - @staticmethod - def from_dict(raw_mapping): ... - -class SpecificationAwareDependencyResolver: ... -class SpecificationPatternDependencyResolver: ... - -class InstallableDependencyResolver: - def install_dependency(self, name, version, type, **kwds): ... - -class Dependency(Dictifiable): - dict_collection_visible_keys = ... # type: Any - cacheable = ... # type: bool - def shell_commands(self, requirement): ... - def exact(self): ... - @property - def resolver_msg(self): ... - -class NullDependency(Dependency): - dependency_type = ... # type: Any - exact = ... # type: bool - version = ... # type: Any - name = ... # type: Any - def __init__(self, version: Optional[Any] = ..., name: Optional[Any] = ...) -> None: ... - @property - def resolver_msg(self): ... - def shell_commands(self, requirement): ... - -class DependencyException(Exception): ... diff --git a/typeshed/galaxy/tools/deps/resolvers/brewed_tool_shed_packages.pyi b/typeshed/galaxy/tools/deps/resolvers/brewed_tool_shed_packages.pyi deleted file mode 100644 index d581de3..0000000 --- a/typeshed/galaxy/tools/deps/resolvers/brewed_tool_shed_packages.pyi +++ /dev/null @@ -1,33 +0,0 @@ -# Stubs for galaxy.tools.deps.resolvers.brewed_tool_shed_packages (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from xml.etree import ElementTree as ET -from .resolver_mixins import UsesHomebrewMixin, UsesInstalledRepositoriesMixin, UsesToolDependencyDirMixin -from ..resolvers import DependencyResolver - -class HomebrewToolShedDependencyResolver(DependencyResolver, UsesHomebrewMixin, UsesToolDependencyDirMixin, UsesInstalledRepositoriesMixin): - resolver_type = ... # type: str - def __init__(self, dependency_manager, **kwds) -> None: ... - def resolve(self, requirement, **kwds): ... - -class RawDependencies: - root = ... # type: Any - dependencies = ... # type: Any - def __init__(self, dependencies_file) -> None: ... - def find(self, package_name, package_version): ... - -class RawDependency: - dependencies = ... # type: Any - package_el = ... # type: Any - repository_el = ... # type: Any - def __init__(self, dependencies, package_el, repository_el) -> None: ... - @property - def repository_owner(self): ... - @property - def repository_name(self): ... - @property - def package_name(self): ... - @property - def package_version(self): ... diff --git a/typeshed/galaxy/tools/deps/resolvers/conda.pyi b/typeshed/galaxy/tools/deps/resolvers/conda.pyi deleted file mode 100644 index 333954d..0000000 --- a/typeshed/galaxy/tools/deps/resolvers/conda.pyi +++ /dev/null @@ -1,72 +0,0 @@ -# Stubs for galaxy.tools.deps.resolvers.conda (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from ..resolvers import Dependency, DependencyResolver, InstallableDependencyResolver, ListableDependencyResolver, MappableDependencyResolver, MultipleDependencyResolver, SpecificationPatternDependencyResolver - -DEFAULT_ENSURE_CHANNELS = ... # type: str - -class CondaDependencyResolver(DependencyResolver, MultipleDependencyResolver, ListableDependencyResolver, InstallableDependencyResolver, SpecificationPatternDependencyResolver, MappableDependencyResolver): - dict_collection_visible_keys = ... # type: Any - resolver_type = ... # type: str - config_options = ... # type: Any - can_uninstall_dependencies = ... # type: bool - versionless = ... # type: Any - dependency_manager = ... # type: Any - conda_prefix_parent = ... # type: Any - ensure_channels = ... # type: Any - auto_init = ... # type: Any - conda_context = ... # type: Any - disabled = ... # type: Any - auto_install = ... # type: Any - copy_dependencies = ... # type: Any - def __init__(self, dependency_manager, **kwds) -> None: ... - def clean(self, **kwds): ... - def uninstall(self, requirements): ... - def uninstall_environments(self, environments): ... - def install_all(self, conda_targets): ... - def resolve_all(self, requirements, **kwds): ... - def merged_environment_name(self, conda_targets): ... - def resolve(self, requirement, **kwds): ... - def unused_dependency_paths(self, toolbox_requirements_status): ... - def list_dependencies(self): ... - def install_dependency(self, name, version, type, **kwds): ... - @property - def prefix(self): ... - -class MergedCondaDependency(Dependency): - dict_collection_visible_keys = ... # type: Any - dependency_type = ... # type: str - activate = ... # type: Any - conda_context = ... # type: Any - environment_path = ... # type: Any - cache_path = ... # type: Any - def __init__(self, conda_context, environment_path, exact, name: Optional[Any] = ..., version: Optional[Any] = ..., preserve_python_environment: bool = ...) -> None: ... - @property - def exact(self): ... - @property - def name(self): ... - @property - def version(self): ... - def shell_commands(self, requirement): ... - -class CondaDependency(Dependency): - dict_collection_visible_keys = ... # type: Any - dependency_type = ... # type: str - cacheable = ... # type: bool - activate = ... # type: Any - conda_context = ... # type: Any - environment_path = ... # type: Any - cache_path = ... # type: Any - def __init__(self, conda_context, environment_path, exact, name: Optional[Any] = ..., version: Optional[Any] = ..., preserve_python_environment: bool = ...) -> None: ... - @property - def exact(self): ... - @property - def name(self): ... - @property - def version(self): ... - def build_cache(self, cache_path): ... - def set_cache_path(self, cache_path): ... - def build_environment(self): ... - def shell_commands(self, requirement): ... diff --git a/typeshed/galaxy/tools/deps/resolvers/galaxy_packages.pyi b/typeshed/galaxy/tools/deps/resolvers/galaxy_packages.pyi deleted file mode 100644 index cb4551f..0000000 --- a/typeshed/galaxy/tools/deps/resolvers/galaxy_packages.pyi +++ /dev/null @@ -1,35 +0,0 @@ -# Stubs for galaxy.tools.deps.resolvers.galaxy_packages (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from .resolver_mixins import UsesToolDependencyDirMixin -from ..resolvers import Dependency, DependencyResolver, ListableDependencyResolver, MappableDependencyResolver - -class GalaxyPackageDependency(Dependency): - dict_collection_visible_keys = ... # type: Any - dependency_type = ... # type: str - script = ... # type: Any - path = ... # type: Any - version = ... # type: Any - name = ... # type: Any - def __init__(self, script, path, version, name, exact: bool = ...) -> None: ... - @property - def exact(self): ... - def shell_commands(self, requirement): ... - -class ToolShedDependency(GalaxyPackageDependency): - dependency_type = ... # type: str - -class BaseGalaxyPackageDependencyResolver(DependencyResolver, UsesToolDependencyDirMixin): - dict_collection_visible_keys = ... # type: Any - dependency_type = ... # type: Any - versionless = ... # type: Any - def __init__(self, dependency_manager, **kwds) -> None: ... - def resolve(self, requirement, **kwds): ... - -class GalaxyPackageDependencyResolver(BaseGalaxyPackageDependencyResolver, ListableDependencyResolver, MappableDependencyResolver): - resolver_type = ... # type: str - def __init__(self, dependency_manager, **kwds) -> None: ... - def resolve(self, requirement, **kwds): ... - def list_dependencies(self): ... diff --git a/typeshed/galaxy/tools/deps/resolvers/homebrew.pyi b/typeshed/galaxy/tools/deps/resolvers/homebrew.pyi deleted file mode 100644 index 7896173..0000000 --- a/typeshed/galaxy/tools/deps/resolvers/homebrew.pyi +++ /dev/null @@ -1,14 +0,0 @@ -# Stubs for galaxy.tools.deps.resolvers.homebrew (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from .resolver_mixins import UsesHomebrewMixin -from ..resolvers import DependencyResolver - -class HomebrewDependencyResolver(DependencyResolver, UsesHomebrewMixin): - resolver_type = ... # type: str - versionless = ... # type: Any - prefer_version = ... # type: Any - def __init__(self, dependency_manager, **kwds) -> None: ... - def resolve(self, requirement, **kwds): ... diff --git a/typeshed/galaxy/tools/deps/resolvers/modules.pyi b/typeshed/galaxy/tools/deps/resolvers/modules.pyi deleted file mode 100644 index 5762d95..0000000 --- a/typeshed/galaxy/tools/deps/resolvers/modules.pyi +++ /dev/null @@ -1,42 +0,0 @@ -# Stubs for galaxy.tools.deps.resolvers.modules (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from ..resolvers import Dependency, DependencyResolver, MappableDependencyResolver - -class ModuleDependencyResolver(DependencyResolver, MappableDependencyResolver): - dict_collection_visible_keys = ... # type: Any - resolver_type = ... # type: str - versionless = ... # type: Any - modulecmd = ... # type: Any - modulepath = ... # type: Any - default_indicator = ... # type: Any - module_checker = ... # type: Any - def __init__(self, dependency_manager, **kwds) -> None: ... - def resolve(self, requirement, **kwds): ... - -class DirectoryModuleChecker: - module_dependency_resolver = ... # type: Any - directories = ... # type: Any - def __init__(self, module_dependency_resolver, modulepath, prefetch) -> None: ... - def has_module(self, module, version): ... - -class AvailModuleChecker: - module_dependency_resolver = ... # type: Any - modulepath = ... # type: Any - default_indicator = ... # type: Any - prefetched_modules = ... # type: Any - def __init__(self, module_dependency_resolver, modulepath, prefetch, default_indicator: Any = ...) -> None: ... - def has_module(self, module, version): ... - -class ModuleDependency(Dependency): - dict_collection_visible_keys = ... # type: Any - dependency_type = ... # type: str - module_dependency_resolver = ... # type: Any - module_name = ... # type: Any - module_version = ... # type: Any - def __init__(self, module_dependency_resolver, module_name, module_version: Optional[Any] = ..., exact: bool = ...) -> None: ... - @property - def exact(self): ... - def shell_commands(self, requirement): ... diff --git a/typeshed/galaxy/tools/deps/resolvers/resolver_mixins.pyi b/typeshed/galaxy/tools/deps/resolvers/resolver_mixins.pyi deleted file mode 100644 index 2b90a98..0000000 --- a/typeshed/galaxy/tools/deps/resolvers/resolver_mixins.pyi +++ /dev/null @@ -1,18 +0,0 @@ -# Stubs for galaxy.tools.deps.resolvers.resolver_mixins (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from ..brew_exts import build_env_statements as build_env_statements, DEFAULT_HOMEBREW_ROOT as DEFAULT_HOMEBREW_ROOT, recipe_cellar_path as recipe_cellar_path -from ..resolvers import Dependency as Dependency, NullDependency as NullDependency - -class UsesHomebrewMixin: ... -class UsesToolDependencyDirMixin: ... -class UsesInstalledRepositoriesMixin: ... - -class HomebrewDependency(Dependency): - commands = ... # type: Any - def __init__(self, commands, exact: bool = ...) -> None: ... - @property - def exact(self): ... - def shell_commands(self, requirement): ... diff --git a/typeshed/galaxy/tools/deps/resolvers/tool_shed_packages.pyi b/typeshed/galaxy/tools/deps/resolvers/tool_shed_packages.pyi deleted file mode 100644 index 224d377..0000000 --- a/typeshed/galaxy/tools/deps/resolvers/tool_shed_packages.pyi +++ /dev/null @@ -1,13 +0,0 @@ -# Stubs for galaxy.tools.deps.resolvers.tool_shed_packages (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from .galaxy_packages import BaseGalaxyPackageDependencyResolver -from .resolver_mixins import UsesInstalledRepositoriesMixin - -class ToolShedPackageDependencyResolver(BaseGalaxyPackageDependencyResolver, UsesInstalledRepositoriesMixin): - resolver_type = ... # type: str - dependency_type = ... # type: Any - resolves_simple_dependencies = ... # type: bool - def __init__(self, dependency_manager, **kwds) -> None: ... diff --git a/typeshed/galaxy/tools/deps/resolvers/unlinked_tool_shed_packages.pyi b/typeshed/galaxy/tools/deps/resolvers/unlinked_tool_shed_packages.pyi deleted file mode 100644 index ddf2ee0..0000000 --- a/typeshed/galaxy/tools/deps/resolvers/unlinked_tool_shed_packages.pyi +++ /dev/null @@ -1,25 +0,0 @@ -# Stubs for galaxy.tools.deps.resolvers.unlinked_tool_shed_packages (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from .galaxy_packages import BaseGalaxyPackageDependencyResolver -from ..resolvers import Dependency - -class UnlinkedToolShedPackageDependencyResolver(BaseGalaxyPackageDependencyResolver): - dict_collection_visible_keys = ... # type: Any - resolver_type = ... # type: str - preferred_owners = ... # type: Any - select_by_owner = ... # type: Any - def __init__(self, dependency_manager, **kwds) -> None: ... - -class CandidateDependency(Dependency): - dict_collection_visible_keys = ... # type: Any - dependency_type = ... # type: str - @property - def exact(self): ... - dependency = ... # type: Any - path = ... # type: Any - owner = ... # type: Any - def __init__(self, dependency, path, owner: Any = ...) -> None: ... - def shell_commands(self, requirement): ... diff --git a/typeshed/galaxy/tools/deps/singularity_util.pyi b/typeshed/galaxy/tools/deps/singularity_util.pyi deleted file mode 100644 index a701d1f..0000000 --- a/typeshed/galaxy/tools/deps/singularity_util.pyi +++ /dev/null @@ -1,7 +0,0 @@ -# Stubs for galaxy.tools.deps.singularity_util (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -def build_singularity_run_command(container_command, image, volumes: Any = ..., env: Any = ..., working_directory: Any = ..., singularity_cmd: Any = ..., run_extra_arguments: Any = ..., sudo: Any = ..., sudo_cmd: Any = ...): ... diff --git a/typeshed/galaxy/tools/deps/views.pyi b/typeshed/galaxy/tools/deps/views.pyi deleted file mode 100644 index 2f57990..0000000 --- a/typeshed/galaxy/tools/deps/views.pyi +++ /dev/null @@ -1,32 +0,0 @@ -# Stubs for galaxy.tools.deps.views (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -class DependencyResolversView: - def __init__(self, app) -> None: ... - def index(self): ... - def show(self, index): ... - def reload(self): ... - def manager_requirements(self): ... - def resolver_requirements(self, index): ... - def manager_dependency(self, **kwds): ... - def resolver_dependency(self, index, **kwds): ... - def show_dependencies(self, tool_requirements_d, installed_tool_dependencies: Optional[Any] = ...): ... - def uninstall_dependencies(self, index: Optional[Any] = ..., **payload): ... - @property - def unused_dependency_paths(self): ... - def remove_unused_dependency_paths(self, envs): ... - def install_dependencies(self, requirements): ... - def install_dependency(self, index: Optional[Any] = ..., **payload): ... - @property - def installable_resolvers(self): ... - @property - def uninstallable_resolvers(self): ... - @property - def tool_ids_by_requirements(self): ... - @property - def toolbox_requirements_status(self): ... - def get_requirements_status(self, tool_requirements_d, installed_tool_dependencies: Optional[Any] = ...): ... - def clean(self, index: Optional[Any] = ..., **kwds): ... diff --git a/typeshed/galaxy/tools/fetcher.pyi b/typeshed/galaxy/tools/fetcher.pyi deleted file mode 100644 index 221bc58..0000000 --- a/typeshed/galaxy/tools/fetcher.pyi +++ /dev/null @@ -1,10 +0,0 @@ -# Stubs for galaxy.tools.fetcher (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -class ToolLocationFetcher: - resolver_classes = ... # type: Any - def __init__(self) -> None: ... - def to_tool_path(self, path_or_uri_like, **kwds): ... diff --git a/typeshed/galaxy/tools/lint.pyi b/typeshed/galaxy/tools/lint.pyi deleted file mode 100644 index 9cd7a26..0000000 --- a/typeshed/galaxy/tools/lint.pyi +++ /dev/null @@ -1,33 +0,0 @@ -# Stubs for galaxy.tools.lint (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from .parser import get_tool_source as get_tool_source - -LEVEL_ALL = ... # type: str -LEVEL_WARN = ... # type: str -LEVEL_ERROR = ... # type: str - -def lint_tool_source(tool_source, level: Any = ..., fail_level: Any = ..., extra_modules: Any = ..., skip_types: Any = ...): ... -def lint_xml(tool_xml, level: Any = ..., fail_level: Any = ..., extra_modules: Any = ..., skip_types: Any = ...): ... -def lint_tool_source_with(lint_context, tool_source, extra_modules: Any = ...): ... -def lint_xml_with(lint_context, tool_xml, extra_modules: Any = ...): ... - -class LintContext: - skip_types = ... # type: Any - level = ... # type: Any - found_errors = ... # type: bool - found_warns = ... # type: bool - def __init__(self, level, skip_types: Any = ...) -> None: ... - printed_linter_info = ... # type: bool - valid_messages = ... # type: Any - info_messages = ... # type: Any - warn_messages = ... # type: Any - error_messages = ... # type: Any - def lint(self, name, lint_func, lint_target): ... - def valid(self, message, *args): ... - def info(self, message, *args): ... - def error(self, message, *args): ... - def warn(self, message, *args): ... - def failed(self, fail_level): ... diff --git a/typeshed/galaxy/tools/lint_util.pyi b/typeshed/galaxy/tools/lint_util.pyi deleted file mode 100644 index e1e1ac0..0000000 --- a/typeshed/galaxy/tools/lint_util.pyi +++ /dev/null @@ -1,5 +0,0 @@ -# Stubs for galaxy.tools.lint_util (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -def is_datasource(tool_xml): ... diff --git a/typeshed/galaxy/tools/linters/__init__.pyi b/typeshed/galaxy/tools/linters/__init__.pyi deleted file mode 100644 index 7f56312..0000000 --- a/typeshed/galaxy/tools/linters/__init__.pyi +++ /dev/null @@ -1,4 +0,0 @@ -# Stubs for galaxy.tools.linters (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - diff --git a/typeshed/galaxy/tools/linters/citations.pyi b/typeshed/galaxy/tools/linters/citations.pyi deleted file mode 100644 index 5378b8d..0000000 --- a/typeshed/galaxy/tools/linters/citations.pyi +++ /dev/null @@ -1,5 +0,0 @@ -# Stubs for galaxy.tools.linters.citations (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -def lint_citations(tool_xml, lint_ctx): ... diff --git a/typeshed/galaxy/tools/linters/command.pyi b/typeshed/galaxy/tools/linters/command.pyi deleted file mode 100644 index 2e68635..0000000 --- a/typeshed/galaxy/tools/linters/command.pyi +++ /dev/null @@ -1,6 +0,0 @@ -# Stubs for galaxy.tools.linters.command (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -def lint_command(tool_xml, lint_ctx): ... -def get_command(tool_xml): ... diff --git a/typeshed/galaxy/tools/linters/cwl.pyi b/typeshed/galaxy/tools/linters/cwl.pyi deleted file mode 100644 index a94292e..0000000 --- a/typeshed/galaxy/tools/linters/cwl.pyi +++ /dev/null @@ -1,12 +0,0 @@ -# Stubs for galaxy.tools.linters.cwl (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -lint_tool_types = ... # type: Any - -def lint_cwl_validation(tool_source, lint_ctx): ... -def lint_new_draft(tool_source, lint_ctx): ... -def lint_docker_image(tool_source, lint_ctx): ... -def lint_description(tool_source, lint_ctx): ... diff --git a/typeshed/galaxy/tools/linters/general.pyi b/typeshed/galaxy/tools/linters/general.pyi deleted file mode 100644 index 812e6e9..0000000 --- a/typeshed/galaxy/tools/linters/general.pyi +++ /dev/null @@ -1,19 +0,0 @@ -# Stubs for galaxy.tools.linters.general (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -ERROR_VERSION_MSG = ... # type: str -VALID_VERSION_MSG = ... # type: str -ERROR_NAME_MSG = ... # type: str -VALID_NAME_MSG = ... # type: str -ERROR_ID_MSG = ... # type: str -VALID_ID_MSG = ... # type: str -PROFILE_PATTERN = ... # type: Any -PROFILE_INFO_DEFAULT_MSG = ... # type: str -PROFILE_INFO_SPECIFIED_MSG = ... # type: str -PROFILE_INVALID_MSG = ... # type: str -lint_tool_types = ... # type: Any - -def lint_general(tool_source, lint_ctx): ... diff --git a/typeshed/galaxy/tools/linters/help.pyi b/typeshed/galaxy/tools/linters/help.pyi deleted file mode 100644 index 306fa3b..0000000 --- a/typeshed/galaxy/tools/linters/help.pyi +++ /dev/null @@ -1,6 +0,0 @@ -# Stubs for galaxy.tools.linters.help (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -def lint_help(tool_xml, lint_ctx): ... -def rst_invalid(text): ... diff --git a/typeshed/galaxy/tools/linters/inputs.pyi b/typeshed/galaxy/tools/linters/inputs.pyi deleted file mode 100644 index c06f46c..0000000 --- a/typeshed/galaxy/tools/linters/inputs.pyi +++ /dev/null @@ -1,8 +0,0 @@ -# Stubs for galaxy.tools.linters.inputs (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from ..lint_util import is_datasource as is_datasource - -def lint_inputs(tool_xml, lint_ctx): ... -def lint_repeats(tool_xml, lint_ctx): ... diff --git a/typeshed/galaxy/tools/linters/outputs.pyi b/typeshed/galaxy/tools/linters/outputs.pyi deleted file mode 100644 index ecb9220..0000000 --- a/typeshed/galaxy/tools/linters/outputs.pyi +++ /dev/null @@ -1,5 +0,0 @@ -# Stubs for galaxy.tools.linters.outputs (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -def lint_output(tool_xml, lint_ctx): ... diff --git a/typeshed/galaxy/tools/linters/stdio.pyi b/typeshed/galaxy/tools/linters/stdio.pyi deleted file mode 100644 index d7c2927..0000000 --- a/typeshed/galaxy/tools/linters/stdio.pyi +++ /dev/null @@ -1,7 +0,0 @@ -# Stubs for galaxy.tools.linters.stdio (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from .command import get_command as get_command - -def lint_stdio(tool_source, lint_ctx): ... diff --git a/typeshed/galaxy/tools/linters/tests.pyi b/typeshed/galaxy/tools/linters/tests.pyi deleted file mode 100644 index d9c7cf0..0000000 --- a/typeshed/galaxy/tools/linters/tests.pyi +++ /dev/null @@ -1,7 +0,0 @@ -# Stubs for galaxy.tools.linters.tests (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from ..lint_util import is_datasource as is_datasource - -def lint_tsts(tool_xml, lint_ctx): ... diff --git a/typeshed/galaxy/tools/linters/xml_order.pyi b/typeshed/galaxy/tools/linters/xml_order.pyi deleted file mode 100644 index a3904f6..0000000 --- a/typeshed/galaxy/tools/linters/xml_order.pyi +++ /dev/null @@ -1,10 +0,0 @@ -# Stubs for galaxy.tools.linters.xml_order (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -TAG_ORDER = ... # type: Any -DATASOURCE_TAG_ORDER = ... # type: Any - -def lint_xml_order(tool_xml, lint_ctx): ... diff --git a/typeshed/galaxy/tools/loader.pyi b/typeshed/galaxy/tools/loader.pyi deleted file mode 100644 index 4e7cd7f..0000000 --- a/typeshed/galaxy/tools/loader.pyi +++ /dev/null @@ -1,8 +0,0 @@ -# Stubs for galaxy.tools.loader (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from galaxy.util.xml_macros import imported_macro_paths as imported_macro_paths, raw_tool_xml_tree as raw_tool_xml_tree, template_macro_params as template_macro_params - -load_tool = ... # type: Any diff --git a/typeshed/galaxy/tools/loader_directory.pyi b/typeshed/galaxy/tools/loader_directory.pyi deleted file mode 100644 index 628289f..0000000 --- a/typeshed/galaxy/tools/loader_directory.pyi +++ /dev/null @@ -1,15 +0,0 @@ -# Stubs for galaxy.tools.loader_directory (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -def find_possible_tools_from_path(path, recursive: bool = ..., enable_beta_formats: bool = ...): ... -def load_tool_sources_from_path(path, load_exception_handler: Any = ..., recursive: bool = ..., register_load_errors: bool = ...): ... -def load_tool_elements_from_path(path, load_exception_handler: Any = ..., recursive: bool = ..., register_load_errors: bool = ...): ... -def is_tool_load_error(obj): ... -def looks_like_a_tool_xml(path): ... -def is_a_yaml_with_class(path, classes): ... -def looks_like_a_tool_yaml(path): ... -def looks_like_a_cwl_artifact(path, classes: Optional[Any] = ...): ... -def looks_like_a_tool_cwl(path): ... diff --git a/typeshed/galaxy/tools/locations/__init__.pyi b/typeshed/galaxy/tools/locations/__init__.pyi deleted file mode 100644 index af99abd..0000000 --- a/typeshed/galaxy/tools/locations/__init__.pyi +++ /dev/null @@ -1,7 +0,0 @@ -# Stubs for galaxy.tools.locations (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -class ToolLocationResolver: - def scheme(self): ... - def get_tool_source_path(self, uri_like): ... diff --git a/typeshed/galaxy/tools/locations/dockstore.pyi b/typeshed/galaxy/tools/locations/dockstore.pyi deleted file mode 100644 index 3420e1e..0000000 --- a/typeshed/galaxy/tools/locations/dockstore.pyi +++ /dev/null @@ -1,19 +0,0 @@ -# Stubs for galaxy.tools.locations.dockstore (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from ..locations import ToolLocationResolver - -class DockStoreResolver(ToolLocationResolver): - scheme = ... # type: str - def get_tool_source_path(self, uri_like): ... - -class _Ga4ghToolClient: - base_url = ... # type: Any - def __init__(self, base_url: str = ...) -> None: ... - def get_tools(self): ... - def get_tool(self, tool_id): ... - def get_tool_version(self, tool_id, version: str = ...): ... - def get_tool_descriptor(self, tool_id, version: str = ..., tool_type: str = ...): ... - def get_tool_cwl(self, tool_id, version: str = ..., as_string: bool = ...): ... diff --git a/typeshed/galaxy/tools/locations/file.pyi b/typeshed/galaxy/tools/locations/file.pyi deleted file mode 100644 index 8268d65..0000000 --- a/typeshed/galaxy/tools/locations/file.pyi +++ /dev/null @@ -1,9 +0,0 @@ -# Stubs for galaxy.tools.locations.file (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from ..locations import ToolLocationResolver as ToolLocationResolver - -class HttpToolResolver(ToolLocationResolver): - scheme = ... # type: str - def get_tool_source_path(self, uri_like): ... diff --git a/typeshed/galaxy/tools/locations/http.pyi b/typeshed/galaxy/tools/locations/http.pyi deleted file mode 100644 index 2687afc..0000000 --- a/typeshed/galaxy/tools/locations/http.pyi +++ /dev/null @@ -1,13 +0,0 @@ -# Stubs for galaxy.tools.locations.http (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from ..locations import ToolLocationResolver - -class HttpToolResolver(ToolLocationResolver): - scheme = ... # type: str - def __init__(self, **kwds) -> None: ... - def get_tool_source_path(self, uri_like): ... - -class HttpsToolResolver(HttpToolResolver): - scheme = ... # type: str diff --git a/typeshed/galaxy/tools/parser/__init__.pyi b/typeshed/galaxy/tools/parser/__init__.pyi deleted file mode 100644 index 0b1bc81..0000000 --- a/typeshed/galaxy/tools/parser/__init__.pyi +++ /dev/null @@ -1,7 +0,0 @@ -# Stubs for galaxy.tools.parser (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from .factory import get_input_source as get_input_source, get_tool_source as get_tool_source -from .interface import ToolSource as ToolSource -from .output_objects import ToolOutputCollectionPart as ToolOutputCollectionPart diff --git a/typeshed/galaxy/tools/parser/cwl.pyi b/typeshed/galaxy/tools/parser/cwl.pyi deleted file mode 100644 index 1b754a9..0000000 --- a/typeshed/galaxy/tools/parser/cwl.pyi +++ /dev/null @@ -1,41 +0,0 @@ -# Stubs for galaxy.tools.parser.cwl (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from .interface import PageSource as PageSource -from .interface import PagesSource as PagesSource -from .interface import ToolSource as ToolSource -from .interface import ToolStdioExitCode as ToolStdioExitCode -from .output_actions import ToolOutputActionGroup as ToolOutputActionGroup -from .output_objects import ToolOutput as ToolOutput -from .yaml import YamlInputSource as YamlInputSource - -log = ... # type: Any - -class CwlToolSource(ToolSource): - def __init__(self, tool_file, strict_cwl_validation: bool = ...) -> None: ... - @property - def tool_proxy(self): ... - def parse_tool_type(self): ... - def parse_id(self): ... - def parse_name(self): ... - def parse_command(self): ... - def parse_environment_variables(self): ... - def parse_edam_operations(self): ... - def parse_edam_topics(self): ... - def parse_help(self): ... - def parse_sanitize(self): ... - def parse_strict_shell(self): ... - def parse_stdio(self): ... - def parse_interpreter(self): ... - def parse_version(self): ... - def parse_description(self): ... - def parse_input_pages(self): ... - def parse_outputs(self, tool): ... - def parse_requirements_and_containers(self): ... - def parse_profile(self): ... - -class CwlPageSource(PageSource): - def __init__(self, tool_proxy) -> None: ... - def parse_input_sources(self): ... diff --git a/typeshed/galaxy/tools/parser/factory.pyi b/typeshed/galaxy/tools/parser/factory.pyi deleted file mode 100644 index c6b63d0..0000000 --- a/typeshed/galaxy/tools/parser/factory.pyi +++ /dev/null @@ -1,9 +0,0 @@ -# Stubs for galaxy.tools.parser.factory (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from galaxy.tools.loader import load_tool as load_tool_xml - -def get_tool_source(config_file: Optional[Any] = ..., xml_tree: Optional[Any] = ..., enable_beta_formats: bool = ..., tool_location_fetcher: Optional[Any] = ...): ... -def get_input_source(content): ... diff --git a/typeshed/galaxy/tools/parser/interface.pyi b/typeshed/galaxy/tools/parser/interface.pyi deleted file mode 100644 index e219c74..0000000 --- a/typeshed/galaxy/tools/parser/interface.pyi +++ /dev/null @@ -1,96 +0,0 @@ -# Stubs for galaxy.tools.parser.interface (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -NOT_IMPLEMENTED_MESSAGE = ... # type: str - -class ToolSource: - default_is_multi_byte = ... # type: bool - def parse_id(self): ... - def parse_version(self): ... - def parse_tool_module(self): ... - def parse_action_module(self): ... - def parse_tool_type(self): ... - def parse_name(self): ... - def parse_description(self): ... - def parse_is_multi_byte(self): ... - def parse_display_interface(self, default): ... - def parse_require_login(self, default): ... - def parse_request_param_translation_elem(self): ... - def parse_command(self): ... - def parse_environment_variables(self): ... - def parse_interpreter(self): ... - def parse_redirect_url_params_elem(self): ... - def parse_version_command(self): ... - def parse_version_command_interpreter(self): ... - def parse_parallelism(self): ... - def parse_hidden(self): ... - def parse_sanitize(self): ... - def parse_refresh(self): ... - def parse_requirements_and_containers(self): ... - def parse_input_pages(self): ... - def parse_outputs(self, tool): ... - def parse_strict_shell(self): ... - def parse_stdio(self): ... - def parse_help(self): ... - def parse_profile(self): ... - def parse_tests_to_dict(self): ... - -class PagesSource: - page_sources = ... # type: Any - def __init__(self, page_sources) -> None: ... - @property - def inputs_defined(self): ... - -class PageSource: - def parse_display(self): ... - def parse_input_sources(self): ... - -class InputSource: - default_optional = ... # type: bool - def elem(self): ... - def get(self, key, value: Optional[Any] = ...): ... - def get_bool(self, key, default): ... - def parse_label(self): ... - def parse_help(self): ... - def parse_sanitizer_elem(self): ... - def parse_validator_elems(self): ... - def parse_optional(self, default: Optional[Any] = ...): ... - def parse_dynamic_options_elem(self): ... - def parse_static_options(self): ... - def parse_conversion_tuples(self): ... - def parse_nested_inputs_source(self): ... - def parse_test_input_source(self): ... - def parse_when_input_sources(self): ... - -class ToolStdioRegex: - match = ... # type: str - stdout_match = ... # type: bool - stderr_match = ... # type: bool - error_level = ... # type: str - desc = ... # type: str - def __init__(self) -> None: ... - -class ToolStdioExitCode: - range_start = ... # type: Any - range_end = ... # type: Any - error_level = ... # type: str - desc = ... # type: str - def __init__(self) -> None: ... - -class TestCollectionDef: - elements = ... # type: Any - collection_type = ... # type: Any - name = ... # type: Any - def __init__(self, elem, parse_param_elem) -> None: ... - def collect_inputs(self): ... - -class TestCollectionOutputDef: - name = ... # type: Any - collection_type = ... # type: Any - count = ... # type: Any - attrib = ... # type: Any - element_tests = ... # type: Any - def __init__(self, name, attrib, element_tests) -> None: ... diff --git a/typeshed/galaxy/tools/parser/output_actions.pyi b/typeshed/galaxy/tools/parser/output_actions.pyi deleted file mode 100644 index 5945acd..0000000 --- a/typeshed/galaxy/tools/parser/output_actions.pyi +++ /dev/null @@ -1,215 +0,0 @@ -# Stubs for galaxy.tools.parser.output_actions (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -log = ... # type: Any -COLLECTION_ATTRIBUTES = ... # type: Any - -class ToolOutputActionGroup: - tag = ... # type: str - parent = ... # type: Any - actions = ... # type: Any - def __init__(self, parent, config_elem) -> None: ... - def apply_action(self, output_dataset, other_values): ... - @property - def tool(self): ... - def __len__(self): ... - -class ToolOutputActionConditionalWhen(ToolOutputActionGroup): - tag = ... # type: str - @classmethod - def from_elem(cls, parent, when_elem): ... - value = ... # type: Any - def __init__(self, parent, config_elem, value) -> None: ... - def is_case(self, output_dataset, other_values): ... - def get_ref(self, output_dataset, other_values): ... - def apply_action(self, output_dataset, other_values): ... - -class ValueToolOutputActionConditionalWhen(ToolOutputActionConditionalWhen): - tag = ... # type: str - def is_case(self, output_dataset, other_values): ... - -class DatatypeIsInstanceToolOutputActionConditionalWhen(ToolOutputActionConditionalWhen): - tag = ... # type: str - value = ... # type: Any - def __init__(self, parent, config_elem, value) -> None: ... - def is_case(self, output_dataset, other_values): ... - -class ToolOutputActionConditional: - tag = ... # type: str - parent = ... # type: Any - name = ... # type: Any - cases = ... # type: Any - def __init__(self, parent, config_elem) -> None: ... - def apply_action(self, output_dataset, other_values): ... - @property - def tool(self): ... - -class ToolOutputAction: - tag = ... # type: str - @classmethod - def from_elem(cls, parent, elem): ... - parent = ... # type: Any - default = ... # type: Any - option = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def apply_action(self, output_dataset, other_values): ... - @property - def tool(self): ... - -class ToolOutputActionOption: - tag = ... # type: str - @classmethod - def from_elem(cls, parent, elem): ... - parent = ... # type: Any - filters = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def get_value(self, other_values): ... - @property - def tool(self): ... - -class NullToolOutputActionOption(ToolOutputActionOption): - tag = ... # type: str - def get_value(self, other_values): ... - -class FromFileToolOutputActionOption(ToolOutputActionOption): - tag = ... # type: str - name = ... # type: Any - column = ... # type: Any - offset = ... # type: Any - separator = ... # type: Any - options = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def get_value(self, other_values): ... - -class FromParamToolOutputActionOption(ToolOutputActionOption): - tag = ... # type: str - name = ... # type: Any - column = ... # type: Any - offset = ... # type: Any - param_attribute = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def get_value(self, other_values): ... - -class FromDataTableOutputActionOption(ToolOutputActionOption): - tag = ... # type: str - name = ... # type: Any - missing_tool_data_table_name = ... # type: Any - options = ... # type: Any - column = ... # type: Any - offset = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def get_value(self, other_values): ... - -class MetadataToolOutputAction(ToolOutputAction): - tag = ... # type: str - name = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def apply_action(self, output_dataset, other_values): ... - -class FormatToolOutputAction(ToolOutputAction): - tag = ... # type: str - default = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def apply_action(self, output_dataset, other_values): ... - -class ToolOutputActionOptionFilter: - tag = ... # type: str - @classmethod - def from_elem(cls, parent, elem): ... - parent = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def filter_options(self, options, other_values): ... - @property - def tool(self): ... - -class ParamValueToolOutputActionOptionFilter(ToolOutputActionOptionFilter): - tag = ... # type: str - ref = ... # type: Any - value = ... # type: Any - column = ... # type: Any - keep = ... # type: Any - compare = ... # type: Any - cast = ... # type: Any - param_attribute = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def filter_options(self, options, other_values): ... - -class InsertColumnToolOutputActionOptionFilter(ToolOutputActionOptionFilter): - tag = ... # type: str - ref = ... # type: Any - value = ... # type: Any - column = ... # type: Any - iterate = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def filter_options(self, options, other_values): ... - -class MultipleSplitterFilter(ToolOutputActionOptionFilter): - tag = ... # type: str - column = ... # type: Any - separator = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def filter_options(self, options, other_values): ... - -class ColumnStripFilter(ToolOutputActionOptionFilter): - tag = ... # type: str - column = ... # type: Any - strip = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def filter_options(self, options, other_values): ... - -class ColumnReplaceFilter(ToolOutputActionOptionFilter): - tag = ... # type: str - old_column = ... # type: Any - old_value = ... # type: Any - new_value = ... # type: Any - new_column = ... # type: Any - column = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def filter_options(self, options, other_values): ... - -class MetadataValueFilter(ToolOutputActionOptionFilter): - tag = ... # type: str - ref = ... # type: Any - name = ... # type: Any - column = ... # type: Any - keep = ... # type: Any - compare = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def filter_options(self, options, other_values): ... - -class BooleanFilter(ToolOutputActionOptionFilter): - tag = ... # type: str - column = ... # type: Any - keep = ... # type: Any - cast = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def filter_options(self, options, other_values): ... - -class StringFunctionFilter(ToolOutputActionOptionFilter): - tag = ... # type: str - column = ... # type: Any - function = ... # type: Any - def __init__(self, parent, elem) -> None: ... - def filter_options(self, options, other_values): ... - -action_types = ... # type: Any -option_types = ... # type: Any -filter_types = ... # type: Any - -def parse_cast_attribute(cast): ... -def parse_compare_type(compare): ... -def compare_eq(value1, value2): ... -def compare_neq(value1, value2): ... -def compare_gt(value1, value2): ... -def compare_gte(value1, value2): ... -def compare_lt(value1, value2): ... -def compare_lte(value1, value2): ... -def compare_in(value1, value2): ... -def compare_startswith(value1, value2): ... -def compare_endswith(value1, value2): ... -def compare_re_search(value1, value2): ... - -compare_types = ... # type: Any diff --git a/typeshed/galaxy/tools/parser/output_collection_def.pyi b/typeshed/galaxy/tools/parser/output_collection_def.pyi deleted file mode 100644 index 2cc4b1b..0000000 --- a/typeshed/galaxy/tools/parser/output_collection_def.pyi +++ /dev/null @@ -1,29 +0,0 @@ -# Stubs for galaxy.tools.parser.output_collection_def (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -DEFAULT_EXTRA_FILENAME_PATTERN = ... # type: str -DEFAULT_SORT_BY = ... # type: str -DEFAULT_SORT_COMP = ... # type: str -NAMED_PATTERNS = ... # type: Any -INPUT_DBKEY_TOKEN = ... # type: str -LEGACY_DEFAULT_DBKEY = ... # type: Any - -def dataset_collector_descriptions_from_elem(elem, legacy: bool = ...): ... -def dataset_collector_descriptions_from_list(discover_datasets_dicts): ... - -class DatasetCollectionDescription: - pattern = ... # type: Any - default_dbkey = ... # type: Any - default_ext = ... # type: Any - default_visible = ... # type: Any - directory = ... # type: Any - assign_primary_output = ... # type: Any - sort_reverse = ... # type: bool - sort_key = ... # type: Any - sort_comp = ... # type: Any - def __init__(self, **kwargs) -> None: ... - -DEFAULT_DATASET_COLLECTOR_DESCRIPTION = ... # type: Any diff --git a/typeshed/galaxy/tools/parser/output_objects.pyi b/typeshed/galaxy/tools/parser/output_objects.pyi deleted file mode 100644 index 68f824e..0000000 --- a/typeshed/galaxy/tools/parser/output_objects.pyi +++ /dev/null @@ -1,68 +0,0 @@ -# Stubs for galaxy.tools.parser.output_objects (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from galaxy.util.dictifiable import Dictifiable - -class ToolOutputBase(Dictifiable): - name = ... # type: Any - label = ... # type: Any - filters = ... # type: Any - hidden = ... # type: Any - collection = ... # type: bool - def __init__(self, name, label: Optional[Any] = ..., filters: Optional[Any] = ..., hidden: bool = ...) -> None: ... - -class ToolOutput(ToolOutputBase): - dict_collection_visible_keys = ... # type: Any - format = ... # type: Any - format_source = ... # type: Any - metadata_source = ... # type: Any - parent = ... # type: Any - actions = ... # type: Any - change_format = ... # type: Any - implicit = ... # type: Any - from_work_dir = ... # type: Any - def __init__(self, name, format: Optional[Any] = ..., format_source: Optional[Any] = ..., metadata_source: Optional[Any] = ..., parent: Optional[Any] = ..., label: Optional[Any] = ..., filters: Optional[Any] = ..., actions: Optional[Any] = ..., hidden: bool = ..., implicit: bool = ...) -> None: ... - def __len__(self): ... - def __getitem__(self, index): ... - def __iter__(self): ... - def to_dict(self, view: str = ..., value_mapper: Optional[Any] = ..., app: Optional[Any] = ...): ... - -class ToolOutputCollection(ToolOutputBase): - collection = ... # type: bool - default_format = ... # type: Any - structure = ... # type: Any - outputs = ... # type: Any - inherit_format = ... # type: Any - inherit_metadata = ... # type: Any - metadata_source = ... # type: Any - format_source = ... # type: Any - change_format = ... # type: Any - def __init__(self, name, structure, label: Optional[Any] = ..., filters: Optional[Any] = ..., hidden: bool = ..., default_format: str = ..., default_format_source: Optional[Any] = ..., default_metadata_source: Optional[Any] = ..., inherit_format: bool = ..., inherit_metadata: bool = ...) -> None: ... - def known_outputs(self, inputs, type_registry): ... - @property - def dynamic_structure(self): ... - @property - def dataset_collector_descriptions(self): ... - -class ToolOutputCollectionStructure: - collection_type = ... # type: Any - collection_type_source = ... # type: Any - structured_like = ... # type: Any - dataset_collector_descriptions = ... # type: Any - dynamic = ... # type: Any - def __init__(self, collection_type, collection_type_source, structured_like, dataset_collector_descriptions) -> None: ... - -class ToolOutputCollectionPart: - output_collection_def = ... # type: Any - element_identifier = ... # type: Any - output_def = ... # type: Any - parent_ids = ... # type: Any - def __init__(self, output_collection_def, element_identifier, output_def, parent_ids: Any = ...) -> None: ... - @property - def effective_output_name(self): ... - @staticmethod - def is_named_collection_part_name(name): ... - @staticmethod - def split_output_name(name): ... diff --git a/typeshed/galaxy/tools/parser/util.pyi b/typeshed/galaxy/tools/parser/util.pyi deleted file mode 100644 index 97b3396..0000000 --- a/typeshed/galaxy/tools/parser/util.pyi +++ /dev/null @@ -1,9 +0,0 @@ -# Stubs for galaxy.tools.parser.util (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from .interface import ToolStdioExitCode as ToolStdioExitCode -from .interface import ToolStdioRegex as ToolStdioRegex - -def error_on_exit_code(): ... -def aggressive_error_checks(): ... diff --git a/typeshed/galaxy/tools/parser/xml.pyi b/typeshed/galaxy/tools/parser/xml.pyi deleted file mode 100644 index ffdd7e9..0000000 --- a/typeshed/galaxy/tools/parser/xml.pyi +++ /dev/null @@ -1,89 +0,0 @@ -# Stubs for galaxy.tools.parser.xml (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from .interface import InputSource as InputSource, PageSource as PageSource, PagesSource as PagesSource, TestCollectionDef as TestCollectionDef, TestCollectionOutputDef as TestCollectionOutputDef, ToolSource as ToolSource, ToolStdioExitCode as ToolStdioExitCode, ToolStdioRegex as ToolStdioRegex -from .output_actions import ToolOutputActionGroup as ToolOutputActionGroup -from .output_collection_def import dataset_collector_descriptions_from_elem as dataset_collector_descriptions_from_elem -from .output_objects import ToolOutput as ToolOutput, ToolOutputCollection as ToolOutputCollection, ToolOutputCollectionStructure as ToolOutputCollectionStructure -from .util import aggressive_error_checks as aggressive_error_checks, error_on_exit_code as error_on_exit_code - -log = ... # type: Any - -class XmlToolSource(ToolSource): - xml_tree = ... # type: Any - root = ... # type: Any - legacy_defaults = ... # type: Any - def __init__(self, xml_tree, source_path: Optional[Any] = ...) -> None: ... - def parse_version(self): ... - def parse_id(self): ... - def parse_tool_module(self): ... - def parse_action_module(self): ... - def parse_tool_type(self): ... - def parse_name(self): ... - def parse_edam_operations(self): ... - def parse_edam_topics(self): ... - def parse_description(self): ... - def parse_is_multi_byte(self): ... - def parse_display_interface(self, default): ... - def parse_require_login(self, default): ... - def parse_request_param_translation_elem(self): ... - def parse_command(self): ... - def parse_environment_variables(self): ... - def parse_interpreter(self): ... - def parse_version_command(self): ... - def parse_version_command_interpreter(self): ... - def parse_parallelism(self): ... - def parse_hidden(self): ... - def parse_redirect_url_params_elem(self): ... - def parse_sanitize(self): ... - def parse_refresh(self): ... - def parse_requirements_and_containers(self): ... - def parse_input_pages(self): ... - def parse_outputs(self, tool): ... - def parse_stdio(self): ... - def parse_strict_shell(self): ... - def parse_help(self): ... - def parse_tests_to_dict(self): ... - def parse_profile(self): ... - -class StdioParser: - stdio_exit_codes = ... # type: Any - stdio_regexes = ... # type: Any - def __init__(self, root) -> None: ... - def parse_stdio_exit_codes(self, stdio_elem): ... - def parse_stdio_regexes(self, stdio_elem): ... - def parse_error_level(self, err_level): ... - -class XmlPagesSource(PagesSource): - input_elem = ... # type: Any - def __init__(self, root) -> None: ... - @property - def inputs_defined(self): ... - -class XmlPageSource(PageSource): - parent_elem = ... # type: Any - def __init__(self, parent_elem) -> None: ... - def parse_display(self): ... - def parse_input_sources(self): ... - -class XmlInputSource(InputSource): - input_elem = ... # type: Any - input_type = ... # type: Any - def __init__(self, input_elem) -> None: ... - def parse_input_type(self): ... - def elem(self): ... - def get(self, key, value: Optional[Any] = ...): ... - def get_bool(self, key, default): ... - def parse_label(self): ... - def parse_help(self): ... - def parse_sanitizer_elem(self): ... - def parse_validator_elems(self): ... - def parse_dynamic_options_elem(self): ... - def parse_static_options(self): ... - def parse_optional(self, default: Optional[Any] = ...): ... - def parse_conversion_tuples(self): ... - def parse_nested_inputs_source(self): ... - def parse_test_input_source(self): ... - def parse_when_input_sources(self): ... diff --git a/typeshed/galaxy/tools/parser/yaml.pyi b/typeshed/galaxy/tools/parser/yaml.pyi deleted file mode 100644 index ccf2afd..0000000 --- a/typeshed/galaxy/tools/parser/yaml.pyi +++ /dev/null @@ -1,56 +0,0 @@ -# Stubs for galaxy.tools.parser.yaml (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from .interface import InputSource as InputSource -from .interface import PageSource as PageSource -from .interface import PagesSource as PagesSource -from .interface import ToolSource as ToolSource -from .output_actions import ToolOutputActionGroup as ToolOutputActionGroup -from .output_collection_def import dataset_collector_descriptions_from_list as dataset_collector_descriptions_from_list -from .output_objects import ToolOutput as ToolOutput, ToolOutputCollection as ToolOutputCollection, ToolOutputCollectionStructure as ToolOutputCollectionStructure -from .util import error_on_exit_code as error_on_exit_code - -class YamlToolSource(ToolSource): - root_dict = ... # type: Any - def __init__(self, root_dict, source_path: Optional[Any] = ...) -> None: ... - def parse_id(self): ... - def parse_version(self): ... - def parse_name(self): ... - def parse_description(self): ... - def parse_edam_operations(self): ... - def parse_edam_topics(self): ... - def parse_is_multi_byte(self): ... - def parse_sanitize(self): ... - def parse_display_interface(self, default): ... - def parse_require_login(self, default): ... - def parse_command(self): ... - def parse_environment_variables(self): ... - def parse_interpreter(self): ... - def parse_version_command(self): ... - def parse_version_command_interpreter(self): ... - def parse_requirements_and_containers(self): ... - def parse_input_pages(self): ... - def parse_strict_shell(self): ... - def parse_stdio(self): ... - def parse_help(self): ... - def parse_outputs(self, tool): ... - def parse_tests_to_dict(self): ... - def parse_profile(self): ... - -class YamlPageSource(PageSource): - inputs_list = ... # type: Any - def __init__(self, inputs_list) -> None: ... - def parse_input_sources(self): ... - -class YamlInputSource(InputSource): - input_dict = ... # type: Any - def __init__(self, input_dict) -> None: ... - def get(self, key, default: Optional[Any] = ...): ... - def get_bool(self, key, default): ... - def parse_input_type(self): ... - def parse_nested_inputs_source(self): ... - def parse_test_input_source(self): ... - def parse_when_input_sources(self): ... - def parse_static_options(self): ... diff --git a/typeshed/galaxy/tools/verify/__init__.pyi b/typeshed/galaxy/tools/verify/__init__.pyi deleted file mode 100644 index 6242553..0000000 --- a/typeshed/galaxy/tools/verify/__init__.pyi +++ /dev/null @@ -1,18 +0,0 @@ -# Stubs for galaxy.tools.verify (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from .asserts import verify_assertions as verify_assertions -from .test_data import TestDataResolver as TestDataResolver - -log = ... # type: Any -DEFAULT_TEST_DATA_RESOLVER = ... # type: Any - -def verify(item_label, output_content, attributes, filename: Optional[Any] = ..., get_filename: Optional[Any] = ..., keep_outputs_dir: Optional[Any] = ..., verify_extra_files: Optional[Any] = ...): ... -def make_temp_fname(fname: Optional[Any] = ...): ... -def check_command(command, description): ... -def files_diff(file1, file2, attributes: Optional[Any] = ...): ... -def files_re_match(file1, file2, attributes: Optional[Any] = ...): ... -def files_re_match_multiline(file1, file2, attributes: Optional[Any] = ...): ... -def files_contains(file1, file2, attributes: Optional[Any] = ...): ... diff --git a/typeshed/galaxy/tools/verify/asserts/__init__.pyi b/typeshed/galaxy/tools/verify/asserts/__init__.pyi deleted file mode 100644 index 3ba17d3..0000000 --- a/typeshed/galaxy/tools/verify/asserts/__init__.pyi +++ /dev/null @@ -1,14 +0,0 @@ -# Stubs for galaxy.tools.verify.asserts (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -log = ... # type: Any -assertion_module_names = ... # type: Any -assertion_modules = ... # type: Any -full_assertion_module_name = ... # type: Any -assertion_module = ... # type: Any - -def verify_assertions(data, assertion_description_list): ... -def verify_assertion(data, assertion_description): ... diff --git a/typeshed/galaxy/tools/verify/asserts/tabular.pyi b/typeshed/galaxy/tools/verify/asserts/tabular.pyi deleted file mode 100644 index 4515eab..0000000 --- a/typeshed/galaxy/tools/verify/asserts/tabular.pyi +++ /dev/null @@ -1,6 +0,0 @@ -# Stubs for galaxy.tools.verify.asserts.tabular (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -def get_first_line(output): ... -def assert_has_n_columns(output, n, sep: str = ...): ... diff --git a/typeshed/galaxy/tools/verify/asserts/text.pyi b/typeshed/galaxy/tools/verify/asserts/text.pyi deleted file mode 100644 index 549d534..0000000 --- a/typeshed/galaxy/tools/verify/asserts/text.pyi +++ /dev/null @@ -1,9 +0,0 @@ -# Stubs for galaxy.tools.verify.asserts.text (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -def assert_has_text(output, text): ... -def assert_not_has_text(output, text): ... -def assert_has_line(output, line): ... -def assert_has_text_matching(output, expression): ... -def assert_has_line_matching(output, expression): ... diff --git a/typeshed/galaxy/tools/verify/asserts/xml.pyi b/typeshed/galaxy/tools/verify/asserts/xml.pyi deleted file mode 100644 index 57af9c7..0000000 --- a/typeshed/galaxy/tools/verify/asserts/xml.pyi +++ /dev/null @@ -1,15 +0,0 @@ -# Stubs for galaxy.tools.verify.asserts.xml (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -def to_xml(output): ... -def xml_find_text(output, path): ... -def xml_find(output, path): ... -def assert_is_valid_xml(output): ... -def assert_has_element_with_path(output, path): ... -def assert_has_n_elements_with_path(output, path, n): ... -def assert_element_text_matches(output, path, expression): ... -def assert_element_text_is(output, path, text): ... -def assert_attribute_matches(output, path, attribute, expression): ... -def assert_attribute_is(output, path, attribute, text): ... -def assert_element_text(output, path, verify_assertions_function, children): ... diff --git a/typeshed/galaxy/tools/verify/test_data.pyi b/typeshed/galaxy/tools/verify/test_data.pyi deleted file mode 100644 index 1fe6f0d..0000000 --- a/typeshed/galaxy/tools/verify/test_data.pyi +++ /dev/null @@ -1,31 +0,0 @@ -# Stubs for galaxy.tools.verify.test_data (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -UPDATE_TEMPLATE = ... # type: Any -UPDATE_FAILED_TEMPLATE = ... # type: Any -LIST_SEP = ... # type: Any - -class TestDataResolver: - resolvers = ... # type: Any - def __init__(self, env_var: str = ..., environ: Any = ...) -> None: ... - def get_filename(self, name): ... - -def build_resolver(uri, environ): ... - -class FileDataResolver: - file_dir = ... # type: Any - def __init__(self, file_dir) -> None: ... - def exists(self, filename): ... - def path(self, filename): ... - -class GitDataResolver(FileDataResolver): - repository = ... # type: Any - updated = ... # type: bool - fetch_data = ... # type: Any - def __init__(self, repository, environ) -> None: ... - def exists(self, filename): ... - def update_repository(self): ... - def execute(self, cmd): ... diff --git a/typeshed/galaxy/util/__init__.pyi b/typeshed/galaxy/util/__init__.pyi deleted file mode 100644 index d2c9a1e..0000000 --- a/typeshed/galaxy/util/__init__.pyi +++ /dev/null @@ -1,131 +0,0 @@ -# Stubs for galaxy.util (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -import collections -from six.moves.urllib import parse as urlparse, request as urlrequest -from .inflection import English as English, Inflector as Inflector - -grp = ... # type: Any -docutils_core = ... # type: Any -docutils_html4css1 = ... # type: Any -inflector = ... # type: Any -log = ... # type: Any -CHUNK_SIZE = ... # type: int -DATABASE_MAX_STRING_SIZE = ... # type: int -DATABASE_MAX_STRING_SIZE_PRETTY = ... # type: str -gzip_magic = ... # type: str -bz2_magic = ... # type: str -DEFAULT_ENCODING = ... # type: Any -NULL_CHAR = ... # type: str -BINARY_CHARS = ... # type: Any -FILENAME_VALID_CHARS = ... # type: str - -def remove_protocol_from_https://github.com/url(url): ... -def is_binary(value, binary_chars: Optional[Any] = ...): ... -def is_uuid(value): ... -def directory_hash_id(id): ... -def get_charset_from_http_headers(headers, default: Optional[Any] = ...): ... -def synchronized(func): ... -def file_iter(fname, sep: Optional[Any] = ...): ... -def file_reader(fp, chunk_size: Any = ...): ... -def unique_id(KEY_SIZE: int = ...): ... -def parse_xml(fname): ... -def parse_xml_string(xml_string): ... -def xml_to_string(elem, pretty: bool = ...): ... -def xml_element_compare(elem1, elem2): ... -def xml_element_list_compare(elem_list1, elem_list2): ... -def xml_element_to_dict(elem): ... -def pretty_print_xml(elem, level: int = ...): ... -def get_file_size(value, default: Optional[Any] = ...): ... -def shrink_stream_by_size(value, size, join_by: str = ..., left_larger: bool = ..., beginning_on_size_error: bool = ..., end_on_size_error: bool = ...): ... -def shrink_string_by_size(value, size, join_by: str = ..., left_larger: bool = ..., beginning_on_size_error: bool = ..., end_on_size_error: bool = ...): ... -def pretty_print_time_interval(time: bool = ..., precise: bool = ...): ... -def pretty_print_json(json_data, is_json_string: bool = ...): ... - -valid_chars = ... # type: Any -mapped_chars = ... # type: Any - -def restore_text(text, character_map: Any = ...): ... -def sanitize_text(text, valid_characters: Any = ..., character_map: Any = ..., invalid_character: str = ...): ... -def sanitize_lists_to_string(values, valid_characters: Any = ..., character_map: Any = ..., invalid_character: str = ...): ... -def sanitize_param(value, valid_characters: Any = ..., character_map: Any = ..., invalid_character: str = ...): ... - -valid_filename_chars = ... # type: Any -invalid_filenames = ... # type: Any - -def sanitize_for_filename(text, default: Optional[Any] = ...): ... -def mask_password_from_https://github.com/url(url): ... -def ready_name_for_url(https://github.com/raw_name): ... -def which(file): ... -def safe_makedirs(path): ... -def in_directory(file, directory, local_path_module: Any = ...): ... -def merge_sorted_iterables(operator, *iterables): ... - -class Params: - NEVER_SANITIZE = ... # type: Any - def __init__(self, params, sanitize: bool = ...) -> None: ... - def flatten(self): ... - def __getattr__(self, name): ... - def get(self, key, default): ... - def __len__(self): ... - def __iter__(self): ... - def update(self, values): ... - -def rst_to_html(s): ... -def xml_text(root, name: Optional[Any] = ...): ... - -truthy = ... # type: Any -falsy = ... # type: Any - -def asbool(obj): ... -def string_as_bool(string): ... -def string_as_bool_or_none(string): ... -def listify(item, do_strip: bool = ...): ... -def commaify(amount): ... -def roundify(amount, sfs: int = ...): ... -def unicodify(value, encoding: Any = ..., error: str = ..., default: Optional[Any] = ...): ... -def smart_str(s, encoding: Any = ..., strings_only: bool = ..., errors: str = ...): ... -def object_to_string(obj): ... -def string_to_object(s): ... - -class ParamsWithSpecs(collections.defaultdict): - specs = ... # type: Any - params = ... # type: Any - def __init__(self, specs: Optional[Any] = ..., params: Optional[Any] = ...) -> None: ... - def __missing__(self, name): ... - def __getattr__(self, name): ... - -def compare_urls(url1, url2, compare_scheme: bool = ..., compare_hostname: bool = ..., compare_path: bool = ...): ... -def read_dbnames(filename): ... -def read_build_sites(filename, check_builds: bool = ...): ... -def relativize_symlinks(path, start: Optional[Any] = ..., followlinks: bool = ...): ... -def stringify_dictionary_keys(in_dict): ... -def recursively_stringify_dictionary_keys(d): ... -def mkstemp_ln(src, prefix: str = ...): ... -def umask_fix_perms(path, umask, unmasked_perms, gid: Optional[Any] = ...): ... -def docstring_trim(docstring): ... -def nice_size(size): ... -def size_to_bytes(size): ... -def send_mail(frm, to, subject, body, config, html: Optional[Any] = ...): ... -def force_symlink(source, link_name): ... -def move_merge(source, target): ... -def safe_str_cmp(a, b): ... - -galaxy_root_path = ... # type: Any - -def galaxy_directory(): ... -def config_directories_from_setting(directories_setting, galaxy_root: Any = ...): ... -def parse_int(value, min_val: Optional[Any] = ..., max_val: Optional[Any] = ..., default: Optional[Any] = ..., allow_none: bool = ...): ... -def parse_non_hex_float(s): ... -def build_url(https://github.com/base_url,%20port:%20int%20=%20...,%20scheme:%20str%20=%20...,%20pathspec:%20Optional[Any]%20=%20...,%20params:%20Optional[Any]%20=%20...,%20doseq:%20bool%20=%20...): ... -def url_get(base_url, password_mgr: Optional[Any] = ..., pathspec: Optional[Any] = ..., params: Optional[Any] = ...): ... -def download_to_file(url, dest_file_path, timeout: int = ..., chunk_size: Any = ...): ... -def safe_relpath(path): ... - -class ExecutionTimer: - begin = ... # type: Any - def __init__(self) -> None: ... - @property - def elapsed(self): ... diff --git a/typeshed/galaxy/util/aliaspickler.pyi b/typeshed/galaxy/util/aliaspickler.pyi deleted file mode 100644 index 95c60a9..0000000 --- a/typeshed/galaxy/util/aliaspickler.pyi +++ /dev/null @@ -1,20 +0,0 @@ -# Stubs for galaxy.util.aliaspickler (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -import pickle -from six.moves import cStringIO as StringIO - -class AliasUnpickler(pickle.Unpickler): - aliases = ... # type: Any - def __init__(self, aliases, *args, **kw) -> None: ... - def find_class(self, module, name): ... - -class AliasPickleModule: - aliases = ... # type: Any - def __init__(self, aliases) -> None: ... - def dump(self, obj, fileobj, protocol: int = ...): ... - def dumps(self, obj, protocol: int = ...): ... - def load(self, fileobj): ... - def loads(self, string): ... diff --git a/typeshed/galaxy/util/bunch.pyi b/typeshed/galaxy/util/bunch.pyi deleted file mode 100644 index 87dc09b..0000000 --- a/typeshed/galaxy/util/bunch.pyi +++ /dev/null @@ -1,17 +0,0 @@ -# Stubs for galaxy.util.bunch (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -class Bunch: - def __init__(self, **kwds) -> None: ... - def dict(self): ... - def get(self, key, default: Optional[Any] = ...): ... - def __iter__(self): ... - def items(self): ... - def keys(self): ... - def values(self): ... - def __nonzero__(self): ... - def __setitem__(self, k, v): ... - def __contains__(self, item): ... diff --git a/typeshed/galaxy/util/checkers.pyi b/typeshed/galaxy/util/checkers.pyi deleted file mode 100644 index cdcb3ef..0000000 --- a/typeshed/galaxy/util/checkers.pyi +++ /dev/null @@ -1,14 +0,0 @@ -# Stubs for galaxy.util.checkers (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -def check_html(file_path, chunk: Optional[Any] = ...): ... -def check_binary(name, file_path: bool = ...): ... -def check_gzip(file_path): ... -def check_bz2(file_path): ... -def check_zip(file_path): ... -def is_bz2(file_path): ... -def is_gzip(file_path): ... -def check_image(file_path): ... diff --git a/typeshed/galaxy/util/compression_utils.pyi b/typeshed/galaxy/util/compression_utils.pyi deleted file mode 100644 index 0c6ca3a..0000000 --- a/typeshed/galaxy/util/compression_utils.pyi +++ /dev/null @@ -1,7 +0,0 @@ -# Stubs for galaxy.util.compression_utils (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from .checkers import is_bz2 as is_bz2, is_gzip as is_gzip - -def get_fileobj(filename, mode: str = ..., gzip_only: bool = ..., bz2_only: bool = ..., zip_only: bool = ...): ... diff --git a/typeshed/galaxy/util/dictifiable.pyi b/typeshed/galaxy/util/dictifiable.pyi deleted file mode 100644 index babdeb4..0000000 --- a/typeshed/galaxy/util/dictifiable.pyi +++ /dev/null @@ -1,8 +0,0 @@ -# Stubs for galaxy.util.dictifiable (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -class Dictifiable: - def to_dict(self, view: str = ..., value_mapper: Optional[Any] = ...): ... diff --git a/typeshed/galaxy/util/expressions.pyi b/typeshed/galaxy/util/expressions.pyi deleted file mode 100644 index f1eca5e..0000000 --- a/typeshed/galaxy/util/expressions.pyi +++ /dev/null @@ -1,18 +0,0 @@ -# Stubs for galaxy.util.expressions (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from collections import MutableMapping - -class ExpressionContext(MutableMapping): - dict = ... # type: Any - parent = ... # type: Any - def __init__(self, dict, parent: Optional[Any] = ...) -> None: ... - def __delitem__(self, key): ... - def __iter__(self): ... - def __len__(self): ... - def __getitem__(self, key): ... - def __setitem__(self, key, value): ... - def __contains__(self, key): ... - def __nonzero__(self): ... diff --git a/typeshed/galaxy/util/filelock.pyi b/typeshed/galaxy/util/filelock.pyi deleted file mode 100644 index f74dd9a..0000000 --- a/typeshed/galaxy/util/filelock.pyi +++ /dev/null @@ -1,21 +0,0 @@ -# Stubs for galaxy.util.filelock (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -class FileLockException(Exception): ... - -class FileLock: - is_locked = ... # type: bool - lockfile = ... # type: Any - file_name = ... # type: Any - timeout = ... # type: Any - delay = ... # type: Any - def __init__(self, file_name, timeout: int = ..., delay: float = ...) -> None: ... - fd = ... # type: Any - def acquire(self): ... - def release(self): ... - def __enter__(self): ... - def __exit__(self, type, value, traceback): ... - def __del__(self): ... diff --git a/typeshed/galaxy/util/hash_util.pyi b/typeshed/galaxy/util/hash_util.pyi deleted file mode 100644 index 1a81a16..0000000 --- a/typeshed/galaxy/util/hash_util.pyi +++ /dev/null @@ -1,14 +0,0 @@ -# Stubs for galaxy.util.hash_util (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -import hashlib as hashlib - -sha1 = ... # type: Any -sha = ... # type: Any -md5 = ... # type: Any - -def new_secure_hash(text_type: Optional[Any] = ...): ... -def hmac_new(key, value): ... -def is_hashable(value): ... diff --git a/typeshed/galaxy/util/heartbeat.pyi b/typeshed/galaxy/util/heartbeat.pyi deleted file mode 100644 index e7152ae..0000000 --- a/typeshed/galaxy/util/heartbeat.pyi +++ /dev/null @@ -1,30 +0,0 @@ -# Stubs for galaxy.util.heartbeat (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -import threading - -def get_current_thread_object_dict(): ... - -class Heartbeat(threading.Thread): - config = ... # type: Any - should_stop = ... # type: bool - period = ... # type: Any - fname = ... # type: Any - file = ... # type: Any - fname_nonsleeping = ... # type: Any - file_nonsleeping = ... # type: Any - pid = ... # type: Any - nonsleeping_heartbeats = ... # type: Any - wait_event = ... # type: Any - def __init__(self, config, name: str = ..., period: int = ..., fname: str = ...) -> None: ... - def run(self): ... - def open_logs(self): ... - def close_logs(self): ... - def dump(self): ... - def shutdown(self): ... - def thread_is_sleeping(self, last_stack_frame): ... - def get_interesting_stack_frame(self, stack_frames): ... - def print_nonsleeping(self, threads_object_dict): ... - def dump_signal_handler(self, signum, frame): ... diff --git a/typeshed/galaxy/util/image_util.pyi b/typeshed/galaxy/util/image_util.pyi deleted file mode 100644 index ce04019..0000000 --- a/typeshed/galaxy/util/image_util.pyi +++ /dev/null @@ -1,13 +0,0 @@ -# Stubs for galaxy.util.image_util (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from PIL import Image as PIL - -PIL = ... # type: Any -log = ... # type: Any - -def image_type(filename): ... -def check_image_type(filename, types): ... -def get_image_ext(file_path): ... diff --git a/typeshed/galaxy/util/inflection.pyi b/typeshed/galaxy/util/inflection.pyi deleted file mode 100644 index 92f01cb..0000000 --- a/typeshed/galaxy/util/inflection.pyi +++ /dev/null @@ -1,46 +0,0 @@ -# Stubs for galaxy.util.inflection (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -class Base: - def cond_plural(self, number_of_records, word): ... - def titleize(self, word, uppercase: str = ...): ... - def camelize(self, word): ... - def underscore(self, word): ... - def humanize(self, word, uppercase: str = ...): ... - def variablize(self, word): ... - def tableize(self, class_name): ... - def classify(self, table_name): ... - def ordinalize(self, number): ... - def unaccent(self, text): ... - def string_replace(self, word, find, replace): ... - def urlize(self, text): ... - def demodulize(self, module_name): ... - def modulize(self, module_description): ... - def foreignKey(self, class_name, separate_class_name_and_id_with_underscore: int = ...): ... - -class English(Base): - def pluralize(self, word): ... - def singularize(self, word): ... - -class Inflector: - Inflector = ... # type: Any - def __init__(self, Inflector: Any = ...) -> None: ... - def pluralize(self, word): ... - def singularize(self, word): ... - def cond_plural(self, number_of_records, word): ... - def titleize(self, word, uppercase: str = ...): ... - def camelize(self, word): ... - def underscore(self, word): ... - def humanize(self, word, uppercase: str = ...): ... - def variablize(self, word): ... - def tableize(self, class_name): ... - def classify(self, table_name): ... - def ordinalize(self, number): ... - def unaccent(self, text): ... - def urlize(self, text): ... - def demodulize(self, module_name): ... - def modulize(self, module_description): ... - def foreignKey(self, class_name, separate_class_name_and_id_with_underscore: int = ...): ... diff --git a/typeshed/galaxy/util/json.pyi b/typeshed/galaxy/util/json.pyi deleted file mode 100644 index d124bd6..0000000 --- a/typeshed/galaxy/util/json.pyi +++ /dev/null @@ -1,12 +0,0 @@ -# Stubs for galaxy.util.json (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -def json_fix(val): ... -def safe_dumps(*args, **kwargs): ... -def validate_jsonrpc_request(request, regular_methods, notification_methods): ... -def validate_jsonrpc_response(response, id: Optional[Any] = ...): ... -def jsonrpc_request(method, params: Optional[Any] = ..., id: Optional[Any] = ..., jsonrpc: str = ...): ... -def jsonrpc_response(request: Optional[Any] = ..., id: Optional[Any] = ..., result: Optional[Any] = ..., error: Optional[Any] = ..., jsonrpc: str = ...): ... diff --git a/typeshed/galaxy/util/lazy_process.pyi b/typeshed/galaxy/util/lazy_process.pyi deleted file mode 100644 index 045e42f..0000000 --- a/typeshed/galaxy/util/lazy_process.pyi +++ /dev/null @@ -1,22 +0,0 @@ -# Stubs for galaxy.util.lazy_process (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -class LazyProcess: - command_and_args = ... # type: Any - thread_lock = ... # type: Any - allow_process_request = ... # type: bool - process = ... # type: Any - def __init__(self, command_and_args) -> None: ... - def start_process(self): ... - def shutdown(self): ... - @property - def running(self): ... - -class NoOpLazyProcess: - def start_process(self): ... - def shutdown(self): ... - @property - def running(self): ... diff --git a/typeshed/galaxy/util/object_wrapper.pyi b/typeshed/galaxy/util/object_wrapper.pyi deleted file mode 100644 index 8a5cda6..0000000 --- a/typeshed/galaxy/util/object_wrapper.pyi +++ /dev/null @@ -1,95 +0,0 @@ -# Stubs for galaxy.util.object_wrapper (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from six.moves import copyreg as copy_reg -from galaxy.util import sanitize_lists_to_string as _sanitize_lists_to_string - -NoneType = ... # type: Any -NotImplementedType = ... # type: Any -EllipsisType = ... # type: Any -XRangeType = ... # type: Any -SliceType = ... # type: Any -BufferType = ... # type: Any -DictProxyType = ... # type: Any -log = ... # type: Any -__CALLABLE_TYPES__ = ... # type: Any -__WRAP_NO_SUBCLASS__ = ... # type: Any -__DONT_SANITIZE_TYPES__ = ... # type: Any -__DONT_WRAP_TYPES__ = ... # type: Any -__WRAP_SEQUENCES__ = ... # type: Any -__WRAP_SETS__ = ... # type: Any -__WRAP_MAPPINGS__ = ... # type: Any -VALID_CHARACTERS = ... # type: Any -CHARACTER_MAP = ... # type: Any -INVALID_CHARACTER = ... # type: str - -def coerce(x, y): ... -def cmp(x, y): ... -def sanitize_lists_to_string(values, valid_characters: Any = ..., character_map: Any = ..., invalid_character: Any = ...): ... -def wrap_with_safe_string(value, no_wrap_classes: Optional[Any] = ...): ... - -class SafeStringWrapper: - __UNSANITIZED_ATTRIBUTE_NAME__ = ... # type: str - __NO_WRAP_NAMES__ = ... # type: Any - def __new__(cls, *arg, **kwd): ... - unsanitized = ... # type: Any - __safe_string_wrapper_function__ = ... # type: Any - def __init__(self, value, safe_string_wrapper_function: Any = ...) -> None: ... - def __lt__(self, other): ... - def __le__(self, other): ... - def __eq__(self, other): ... - def __ne__(self, other): ... - def __gt__(self, other): ... - def __ge__(self, other): ... - def __cmp__(self, other): ... - def __hash__(self): ... - def __bool__(self): ... - __nonzero__ = ... # type: Any - def __getattr__(self, name): ... - def __setattr__(self, name, value): ... - def __delattr__(self, name): ... - def __getattribute__(self, name): ... - def __len__(self): ... - def __getitem__(self, key): ... - def __setitem__(self, key, value): ... - def __delitem__(self, key): ... - def __iter__(self): ... - def __contains__(self, item): ... - def __getslice__(self, i, j): ... - def __setslice__(self, i, j, value): ... - def __delslice__(self, i, j): ... - def __add__(self, other): ... - def __sub__(self, other): ... - def __mul__(self, other): ... - def __floordiv__(self, other): ... - def __mod__(self, other): ... - def __divmod__(self, other): ... - def __pow__(self, *other): ... - def __lshift__(self, other): ... - def __rshift__(self, other): ... - def __and__(self, other): ... - def __xor__(self, other): ... - def __or__(self, other): ... - def __div__(self, other): ... - def __truediv__(self, other): ... - def __rpow__(self, other): ... - def __neg__(self): ... - def __pos__(self): ... - def __abs__(self): ... - def __invert__(self): ... - def __complex__(self): ... - def __int__(self): ... - def __float__(self): ... - def __oct__(self): ... - def __hex__(self): ... - def __index__(self): ... - def __coerce__(self, other): ... - def __enter__(self): ... - def __exit__(self, *args): ... - -class CallableSafeStringWrapper(SafeStringWrapper): - def __call__(self, *args, **kwds): ... - -def pickle_SafeStringWrapper(safe_object): ... diff --git a/typeshed/galaxy/util/odict.pyi b/typeshed/galaxy/util/odict.pyi deleted file mode 100644 index 459e306..0000000 --- a/typeshed/galaxy/util/odict.pyi +++ /dev/null @@ -1,27 +0,0 @@ -# Stubs for galaxy.util.odict (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from six.moves import UserDict - -dict_alias = ... # type: Any - -class odict(UserDict): - def __init__(self, dict: Optional[Any] = ...) -> None: ... - def __delitem__(self, key): ... - def __setitem__(self, key, item): ... - def clear(self): ... - def copy(self): ... - def items(self): ... - def keys(self): ... - def popitem(self): ... - def setdefault(self, key, failobj: Optional[Any] = ...): ... - def update(self, dict): ... - def values(self): ... - def iterkeys(self): ... - def itervalues(self): ... - def iteritems(self): ... - def __iter__(self): ... - def reverse(self): ... - def insert(self, index, key, item): ... diff --git a/typeshed/galaxy/util/oset.pyi b/typeshed/galaxy/util/oset.pyi deleted file mode 100644 index 1d1f7bd..0000000 --- a/typeshed/galaxy/util/oset.pyi +++ /dev/null @@ -1,19 +0,0 @@ -# Stubs for galaxy.util.oset (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -import collections - -class OrderedSet(collections.MutableSet): - end = ... # type: Any - map = ... # type: Any - def __init__(self, iterable: Optional[Any] = ...) -> None: ... - def __len__(self): ... - def __contains__(self, key): ... - def add(self, key): ... - def discard(self, key): ... - def __iter__(self): ... - def __reversed__(self): ... - def pop(self, last: bool = ...): ... - def __eq__(self, other): ... diff --git a/typeshed/galaxy/util/plugin_config.pyi b/typeshed/galaxy/util/plugin_config.pyi deleted file mode 100644 index 887a82b..0000000 --- a/typeshed/galaxy/util/plugin_config.pyi +++ /dev/null @@ -1,11 +0,0 @@ -# Stubs for galaxy.util.plugin_config (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -yaml = ... # type: Any - -def plugins_dict(module, plugin_type_identifier): ... -def load_plugins(plugins_dict, plugin_source, extra_kwds: Any = ...): ... -def plugin_source_from_path(path): ... diff --git a/typeshed/galaxy/util/properties.pyi b/typeshed/galaxy/util/properties.pyi deleted file mode 100644 index b59fdd0..0000000 --- a/typeshed/galaxy/util/properties.pyi +++ /dev/null @@ -1,19 +0,0 @@ -# Stubs for galaxy.util.properties (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional -from six.moves.configparser import ConfigParser - -def find_config_file(default, old_default, explicit, cwd: Optional[Any] = ...): ... -def load_app_properties(kwds: Any = ..., ini_file: Optional[Any] = ..., ini_section: str = ..., config_prefix: str = ...): ... - -class NicerConfigParser(ConfigParser): - filename = ... # type: Any - def __init__(self, filename, *args, **kw) -> None: ... - read_file = ... # type: Any - def defaults(self): ... - class InterpolateWrapper: - def __init__(self, original) -> None: ... - def __getattr__(self, name): ... - def before_get(self, parser, section, option, value, defaults): ... diff --git a/typeshed/galaxy/util/simplegraph.pyi b/typeshed/galaxy/util/simplegraph.pyi deleted file mode 100644 index b1aba1a..0000000 --- a/typeshed/galaxy/util/simplegraph.pyi +++ /dev/null @@ -1,26 +0,0 @@ -# Stubs for galaxy.util.simplegraph (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -class SimpleGraphNode: - index = ... # type: Any - data = ... # type: Any - def __init__(self, index, **data) -> None: ... - -class SimpleGraphEdge: - source_index = ... # type: Any - target_index = ... # type: Any - data = ... # type: Any - def __init__(self, source_index, target_index, **data) -> None: ... - -class SimpleGraph: - nodes = ... # type: Any - edges = ... # type: Any - def __init__(self, nodes: Optional[Any] = ..., edges: Optional[Any] = ...) -> None: ... - def add_node(self, node_id, **data): ... - def add_edge(self, source_id, target_id, **data): ... - def gen_node_dicts(self): ... - def gen_edge_dicts(self): ... - def as_dict(self): ... diff --git a/typeshed/galaxy/util/sleeper.pyi b/typeshed/galaxy/util/sleeper.pyi deleted file mode 100644 index 600adf9..0000000 --- a/typeshed/galaxy/util/sleeper.pyi +++ /dev/null @@ -1,11 +0,0 @@ -# Stubs for galaxy.util.sleeper (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -class Sleeper: - condition = ... # type: Any - def __init__(self) -> None: ... - def sleep(self, seconds): ... - def wake(self): ... diff --git a/typeshed/galaxy/util/sockets.pyi b/typeshed/galaxy/util/sockets.pyi deleted file mode 100644 index 100aba9..0000000 --- a/typeshed/galaxy/util/sockets.pyi +++ /dev/null @@ -1,7 +0,0 @@ -# Stubs for galaxy.util.sockets (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -def unused_port(range: Optional[Any] = ...): ... diff --git a/typeshed/galaxy/util/specs.pyi b/typeshed/galaxy/util/specs.pyi deleted file mode 100644 index e3a95b9..0000000 --- a/typeshed/galaxy/util/specs.pyi +++ /dev/null @@ -1,9 +0,0 @@ -# Stubs for galaxy.util.specs (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -def to_str_or_none(value): ... -def to_bool_or_none(value): ... -def to_bool(value): ... -def to_float_or_none(value): ... -def is_in(*args): ... diff --git a/typeshed/galaxy/util/sqlite.pyi b/typeshed/galaxy/util/sqlite.pyi deleted file mode 100644 index 53c7eae..0000000 --- a/typeshed/galaxy/util/sqlite.pyi +++ /dev/null @@ -1,6 +0,0 @@ -# Stubs for galaxy.util.sqlite (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -def is_read_only_query(query): ... -def connect(path): ... diff --git a/typeshed/galaxy/util/submodules.pyi b/typeshed/galaxy/util/submodules.pyi deleted file mode 100644 index dbae050..0000000 --- a/typeshed/galaxy/util/submodules.pyi +++ /dev/null @@ -1,9 +0,0 @@ -# Stubs for galaxy.util.submodules (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -log = ... # type: Any - -def submodules(module): ... diff --git a/typeshed/galaxy/util/topsort.pyi b/typeshed/galaxy/util/topsort.pyi deleted file mode 100644 index 79396d9..0000000 --- a/typeshed/galaxy/util/topsort.pyi +++ /dev/null @@ -1,20 +0,0 @@ -# Stubs for galaxy.util.topsort (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from galaxy.util.odict import odict as OrderedDict - -class CycleError(Exception): - preds = ... # type: Any - def __init__(self, sofar, numpreds, succs) -> None: ... - def get_partial(self): ... - def get_pred_counts(self): ... - def get_succs(self): ... - def get_elements(self): ... - def get_pairlist(self): ... - def get_preds(self): ... - def pick_a_cycle(self): ... - -def topsort(pairlist): ... -def topsort_levels(pairlist): ... diff --git a/typeshed/galaxy/util/xml_macros.pyi b/typeshed/galaxy/util/xml_macros.pyi deleted file mode 100644 index 27607df..0000000 --- a/typeshed/galaxy/util/xml_macros.pyi +++ /dev/null @@ -1,18 +0,0 @@ -# Stubs for galaxy.util.xml_macros (Python 3.4) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -REQUIRED_PARAMETER = ... # type: Any - -def load(path): ... -def template_macro_params(root): ... -def raw_tool_xml_tree(path): ... -def imported_macro_paths(root): ... - -class XmlMacroDef: - elements = ... # type: Any - parameters = ... # type: Any - def __init__(self, el) -> None: ... - def macro_tokens(self, expand_el): ... diff --git a/typeshed/junit_xml.pyi b/typeshed/junit_xml.pyi deleted file mode 100644 index 1f50f8a..0000000 --- a/typeshed/junit_xml.pyi +++ /dev/null @@ -1,60 +0,0 @@ -# Stubs for junit_xml (Python 3.5) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -unichr = chr - -def decode(var, encoding): ... - -class TestSuite: - name: Any = ... - test_cases: Any = ... - timestamp: Any = ... - hostname: Any = ... - id: Any = ... - package: Any = ... - file: Any = ... - log: Any = ... - url: Any = ... - stdout: Any = ... - stderr: Any = ... - properties: Any = ... - def __init__(self, name, test_cases: Optional[Any] = ..., hostname: Optional[Any] = ..., id: Optional[Any] = ..., package: Optional[Any] = ..., timestamp: Optional[Any] = ..., properties: Optional[Any] = ..., file: Optional[Any] = ..., log: Optional[Any] = ..., url: Optional[Any] = ..., stdout: Optional[Any] = ..., stderr: Optional[Any] = ...) -> None: ... - def build_xml_doc(self, encoding: Optional[Any] = ...): ... - @staticmethod - def to_xml_string(test_suites, prettyprint: bool = ..., encoding: Optional[Any] = ...): ... - @staticmethod - def to_file(file_descriptor, test_suites, prettyprint: bool = ..., encoding: Optional[Any] = ...): ... - -class TestCase: - name: Any = ... - assertions: Any = ... - elapsed_sec: Any = ... - timestamp: Any = ... - classname: Any = ... - status: Any = ... - category: Any = ... - file: Any = ... - line: Any = ... - log: Any = ... - url: Any = ... - stdout: Any = ... - stderr: Any = ... - is_enabled: bool = ... - error_message: Any = ... - error_output: Any = ... - error_type: Any = ... - failure_message: Any = ... - failure_output: Any = ... - failure_type: Any = ... - skipped_message: Any = ... - skipped_output: Any = ... - def __init__(self, name, classname: Optional[Any] = ..., elapsed_sec: Optional[Any] = ..., stdout: Optional[Any] = ..., stderr: Optional[Any] = ..., assertions: Optional[Any] = ..., timestamp: Optional[Any] = ..., status: Optional[Any] = ..., category: Optional[Any] = ..., file: Optional[Any] = ..., line: Optional[Any] = ..., log: Optional[Any] = ..., group: Optional[Any] = ..., url: Optional[Any] = ...) -> None: ... - def add_error_info(self, message: Optional[Any] = ..., output: Optional[Any] = ..., error_type: Optional[Any] = ...): ... - def add_failure_info(self, message: Optional[Any] = ..., output: Optional[Any] = ..., failure_type: Optional[Any] = ...): ... - def add_skipped_info(self, message: Optional[Any] = ..., output: Optional[Any] = ...): ... - def is_failure(self): ... - def is_error(self): ... - def is_skipped(self): ... diff --git a/typeshed/mistune.pyi b/typeshed/mistune.pyi deleted file mode 100644 index d267d92..0000000 --- a/typeshed/mistune.pyi +++ /dev/null @@ -1,271 +0,0 @@ -__author__ = "Aleksandr Slepchenkov" -__email__ = "Sl.aleksandr28@gmail.com" - -from typing import Any, Optional, Pattern, List, Text, Tuple, Dict, Match, Type, Sequence, Iterable - -Tokens = List[Dict[Text, Any]] -# There are too much levels of optional unions of lists of text in cell and align 385 and 396 lines in mistune - - -def escape(text: Text, quote: bool = ..., smart_amp: bool = ...) -> Text: ... - - -class BlockGrammar: - def_links = ... # type: Pattern - def_footnotes = ... # type: Pattern - newline = ... # type: Pattern - block_code = ... # type: Pattern - fences = ... # type: Pattern - hrule = ... # type: Pattern - heading = ... # type: Pattern - lheading = ... # type: Pattern - block_quote = ... # type: Pattern - list_block = ... # type: Pattern - list_item = ... # type: Pattern - list_bullet = ... # type: Pattern - paragraph = ... # type: Pattern - block_html = ... # type: Pattern - table = ... # type: Pattern - nptable = ... # type: Pattern - text = ... # type: Pattern - - -class BlockLexer: - grammar_class = ... # type: Type[BlockGrammar] - default_rules = ... # type: List[Text] - list_rules = ... # type: Tuple[Text] - footnote_rules = ... # type: Tuple[Text] - tokens = ... # type: Tokens - def_links = ... # type: Dict[Text, Dict[Text, Text]] - def_footnotes = ... # type: Dict[Text, int] - rules = ... # type: BlockGrammar - - def __init__(self, rules: Optional[BlockGrammar] = ..., **kwargs) -> None: ... - - def __call__(self, text: Text, rules: Optional[Sequence[Text]] = ...) -> Tokens: ... - - def parse(self, text: Text, rules: Optional[Sequence[Text]] = ...) -> Tokens: ... - - def parse_newline(self, m: Match) -> None: ... - - def parse_block_code(self, m: Match) -> None: ... - - def parse_fences(self, m: Match) -> None: ... - - def parse_heading(self, m: Match) -> None: ... - - def parse_lheading(self, m: Match) -> None: ... - - def parse_hrule(self, m: Match) -> None: ... - - def parse_list_block(self, m: Match) -> None: ... - - def parse_block_quote(self, m: Match) -> None: ... - - def parse_def_links(self, m: Match) -> None: ... - - def parse_def_footnotes(self, m: Match) -> None: ... - - def parse_table(self, m: Match) -> None: ... - - def parse_nptable(self, m: Match) -> None: ... - - def parse_block_html(self, m: Match) -> None: ... - - def parse_paragraph(self, m: Match) -> None: ... - - def parse_text(self, m: Match) -> None: ... - - -class InlineGrammar: - escape = ... # type: Pattern - inline_html = ... # type: Pattern - autolink = ... # type: Pattern - link = ... # type: Pattern - reflink = ... # type: Pattern - nolink = ... # type: Pattern - url = ... # type: Pattern - double_emphasis = ... # type: Pattern - emphasis = ... # type: Pattern - code = ... # type: Pattern - linebreak = ... # type: Pattern - strikethrough = ... # type: Pattern - footnote = ... # type: Pattern - text = ... # type: Pattern - - def hard_wrap(self) -> None: ... - - -class InlineLexer: - grammar_class = ... # type: Type[InlineGrammar] - default_rules = ... # type: List[Text] - inline_html_rules = ... # type: List[Text] - renderer = ... # type: Renderer - links = ... # type: Dict[Any, Dict] - footnotes = ... # type: Dict[Text, int] - footnote_index = ... # type: int - _in_link = ... # type: bool - _in_footnote = ... # type: bool - _parse_inline_html = ... # type: bool - rules = ... # type: InlineGrammar - - def __init__(self, renderer: Renderer, rules: Optional[InlineGrammar] = ..., **kwargs) -> None: ... - - def __call__(self, text: Text, rules: Optional[Sequence[Text]] = ...) -> Text: ... - - def setup(self, links: Optional[Dict[Any, Dict]], footnotes: Optional[Dict[Text, int]]) -> None: ... - - line_match = ... # type: Match - line_started = ... # type: bool - - def output(self, text: Text, rules: Optional[Sequence[Text]] = ...) -> Text: ... - - def output_escape(self, m: Match) -> Text: ... - - def output_autolink(self, m: Match) -> Text: ... - - def output_url(https://github.com/self,%20m:%20Match) -> Text: ... - - def output_inline_html(self, m: Match) -> Text: ... - - def output_footnote(self, m: Match) -> Optional[Text]: ... - - def output_link(self, m: Match) -> Text: ... - - def output_reflink(self, m: Match) -> Optional[Text]: ... - - def output_nolink(self, m: Match) -> Optional[Text]: ... - - def output_double_emphasis(self, m: Match) -> Text: ... - - def output_emphasis(self, m: Match) -> Text: ... - - def output_code(self, m: Match) -> Text: ... - - def output_linebreak(self, m: Match) -> Text: ... - - def output_strikethrough(self, m: Match) -> Text: ... - - def output_text(self, m: Match) -> Text: ... - - -class Renderer: - options = ... # type: Dict - - def __init__(self, **kwargs) -> None: ... - - def placeholder(self) -> Text: ... - - def block_code(self, code: Text, - lang: Any = ...) -> Text: ... # It seems that lang should be string, however other types are valid as well - - def block_quote(self, text: Text) -> Text: ... - - def block_html(self, html: Text) -> Text: ... - - def header(self, text: Text, level: int, raw: Optional[Text] = ...) -> Text: ... - - def hrule(self) -> Text: ... - - def list(self, body: Any, - ordered: bool = ...) -> Text: ... # body - same reason as for lang above, and for other Any in this class - - def list_item(self, text: Any) -> Text: ... - - def paragraph(self, text: Text) -> Text: ... - - def table(self, header: Any, body: Any) -> Text: ... - - def table_row(self, content: Any) -> Text: ... - - def table_cell(self, content: Any, **flags) -> Text: ... - - def double_emphasis(self, text: Any) -> Text: ... - - def emphasis(self, text: Any) -> Text: ... - - def codespan(self, text: Text) -> Text: ... - - def linebreak(self) -> Text: ... - - def strikethrough(self, text: Any) -> Text: ... - - def text(self, text: Any) -> Text: ... - - def escape(self, text: Any) -> Text: ... - - def autolink(self, link: Any, is_email: bool = ...) -> Text: ... - - def link(self, link: Any, title: Any, text: Any) -> Text: ... - - def image(self, src: Any, title: Any, text: Any) -> Text: ... - - def inline_html(self, html: Any) -> Text: ... - - def newline(self) -> Text: ... - - def footnote_ref(self, key: Any, index: int) -> Text: ... - - def footnote_item(self, key: Any, text: Text) -> Text: ... - - def footnotes(self, text: Any) -> Text: ... - - -class Markdown: - renderer = ... # type: Renderer - inline = ... # type: InlineLexer - block = ... # type: BlockLexer - footnotes = ... # type: List[Dict[Text, Any]] - tokens = ... # type: Tokens - - def __init__(self, renderer: Optional[Renderer] = ..., inline: Optional[InlineLexer] = ..., - block: Optional[BlockLexer] = ..., **kwargs) -> None: ... - - def __call__(self, text: Text) -> Text: ... - - def render(self, text: Text) -> Text: ... - - def parse(self, text: Text) -> Text: ... - - token = ... # type: Dict[Text, Any] - - def pop(self) -> Optional[Dict[Text, Any]]: ... - - def peek(self) -> Optional[Dict[Text, Any]]: ... - - def output(self, text: Text, rules: Optional[Sequence[Text]] = ...): ... - - def tok(self) -> Text: ... - - def tok_text(self) -> Text: ... - - def output_newline(self) -> Text: ... - - def output_hrule(self) -> Text: ... - - def output_heading(self) -> Text: ... - - def output_code(self) -> Text: ... - - def output_table(self) -> Text: ... - - def output_block_quote(self) -> Text: ... - - def output_list(self) -> Text: ... - - def output_list_item(self) -> Text: ... - - def output_loose_item(self) -> Text: ... - - def output_footnote(self) -> Text: ... - - def output_close_html(self) -> Text: ... - - def output_open_html(self) -> Text: ... - - def output_paragraph(self) -> Text: ... - - def output_text(self) -> Text: ... - - -def markdown(text: Text, escape: bool = ..., **kwargs) -> Text: ... \ No newline at end of file diff --git a/typeshed/rdflib/__init__.pyi b/typeshed/rdflib/__init__.pyi deleted file mode 100644 index d9587d3..0000000 --- a/typeshed/rdflib/__init__.pyi +++ /dev/null @@ -1,9 +0,0 @@ -# Stubs for rdflib (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from rdflib.term import URIRef as URIRef, BNode as BNode, Literal as Literal, Variable as Variable -from rdflib.namespace import Namespace as Namespace -from rdflib.graph import Dataset as Dataset, Graph as Graph, ConjunctiveGraph as ConjunctiveGraph -from rdflib.namespace import RDF as RDF, RDFS as RDFS, OWL as OWL, XSD as XSD -from rdflib import util as util diff --git a/typeshed/rdflib/events.pyi b/typeshed/rdflib/events.pyi deleted file mode 100644 index 7da9fbe..0000000 --- a/typeshed/rdflib/events.pyi +++ /dev/null @@ -1,12 +0,0 @@ -# Stubs for rdflib.events (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -class Event: - def __init__(self, **kw): ... - -class Dispatcher: - def set_map(self, amap): ... - def get_map(self): ... - def subscribe(self, event_type, handler): ... - def dispatch(self, event): ... diff --git a/typeshed/rdflib/exceptions.pyi b/typeshed/rdflib/exceptions.pyi deleted file mode 100644 index 252af85..0000000 --- a/typeshed/rdflib/exceptions.pyi +++ /dev/null @@ -1,37 +0,0 @@ -# Stubs for rdflib.exceptions (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -class Error(Exception): - msg = ... # type: Any - def __init__(self, msg=None): ... - -class TypeCheckError(Error): - type = ... # type: Any - node = ... # type: Any - def __init__(self, node): ... - -class SubjectTypeError(TypeCheckError): - msg = ... # type: Any - def __init__(self, node): ... - -class PredicateTypeError(TypeCheckError): - msg = ... # type: Any - def __init__(self, node): ... - -class ObjectTypeError(TypeCheckError): - msg = ... # type: Any - def __init__(self, node): ... - -class ContextTypeError(TypeCheckError): - msg = ... # type: Any - def __init__(self, node): ... - -class ParserError(Error): - msg = ... # type: Any - def __init__(self, msg): ... - -class UniquenessError(Error): - def __init__(self, values): ... diff --git a/typeshed/rdflib/graph.pyi b/typeshed/rdflib/graph.pyi deleted file mode 100644 index bf3c076..0000000 --- a/typeshed/rdflib/graph.pyi +++ /dev/null @@ -1,159 +0,0 @@ -# Stubs for rdflib.graph (Python 3) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from rdflib.term import Identifier, Node, BNode -from typing import Any, Iterator, IO, Optional, Text, Tuple, Union - -class Graph(Node): - context_aware: bool = ... - formula_aware: bool = ... - default_union: bool = ... - def __init__(self, store: str = ..., identifier: Optional[Any] = ..., namespace_manager: Optional[Any] = ...) -> None: ... - store: Any = ... - identifier: Any = ... - namespace_manager: Any = ... - def toPython(self): ... - def destroy(self, configuration: Any) -> None: ... - def commit(self) -> None: ... - def rollback(self) -> None: ... - def open(self, configuration: Any, create: bool = ...): ... - def close(self, commit_pending_transaction: bool = ...) -> None: ... - def add(self, xxx_todo_changeme: Any) -> None: ... - def addN(self, quads: Any) -> None: ... - def remove(self, xxx_todo_changeme1: Any) -> None: ... - def triples(self, xxx_todo_changeme2: Tuple[Optional[Union[Text, Identifier]], Optional[Union[Text, Identifier]], Optional[Identifier]]) -> Iterator[Tuple[BNode, BNode, BNode]]: ... - def __getitem__(self, item: Any): ... - def __len__(self): ... - def __iter__(self): ... - def __contains__(self, triple: Any): ... - def __hash__(self): ... - def md5_term_hash(self): ... - def __cmp__(self, other: Any): ... - def __eq__(self, other: Any): ... - def __lt__(self, other: Any): ... - def __le__(self, other: Any): ... - def __gt__(self, other: Any): ... - def __ge__(self, other: Any): ... - def __iadd__(self, other: Any): ... - def __isub__(self, other: Any): ... - def __add__(self, other: Any): ... - def __mul__(self, other: Any): ... - def __sub__(self, other: Any): ... - def __xor__(self, other: Any): ... - __or__: Any = ... - __and__: Any = ... - def set(self, triple: Any) -> None: ... - def subjects(self, predicate: Optional[Any] = ..., object: Optional[Any] = ...) -> None: ... - def predicates(self, subject: Optional[Any] = ..., object: Optional[Any] = ...) -> None: ... - def objects(self, subject: Optional[Any] = ..., predicate: Optional[Any] = ...) -> None: ... - def subject_predicates(self, object: Optional[Any] = ...) -> None: ... - def subject_objects(self, predicate: Optional[Any] = ...) -> None: ... - def predicate_objects(self, subject: Optional[Any] = ...) -> None: ... - def triples_choices(self, xxx_todo_changeme3: Any, context: Optional[Any] = ...) -> None: ... - def value(self, subject: Optional[Any] = ..., predicate: Any = ..., object: Optional[Any] = ..., default: Optional[Any] = ..., any: bool = ...): ... - def label(self, subject: Any, default: str = ...): ... - def preferredLabel(self, subject: Any, lang: Optional[Any] = ..., default: Optional[Any] = ..., labelProperties: Any = ...): ... - def comment(self, subject: Any, default: str = ...): ... - def items(self, list: Any) -> None: ... - def transitiveClosure(self, func: Any, arg: Any, seen: Optional[Any] = ...) -> None: ... - def transitive_objects(self, subject: Any, property: Any, remember: Optional[Any] = ...) -> None: ... - def transitive_subjects(self, predicate: Any, object: Any, remember: Optional[Any] = ...) -> None: ... - def seq(self, subject: Any): ... - def qname(self, uri: Any): ... - def compute_qname(self, uri: Any, generate: bool = ...): ... - def bind(self, prefix: Any, namespace: Any, override: bool = ...): ... - def namespaces(self) -> None: ... - def absolutize(self, uri: Any, defrag: int = ...): ... - def serialize(self, destination: Optional[Any] = ..., format: str = ..., base: Optional[Any] = ..., encoding: Optional[Any] = ..., **args: Any): ... - def parse(self, source: Optional[Any] = ..., publicID: Optional[Any] = ..., format: Optional[Any] = ..., location: Optional[Any] = ..., file: Optional[Any] = ..., data: Optional[Any] = ..., **args: Any): ... - def load(self, source: Any, publicID: Optional[Any] = ..., format: str = ...) -> None: ... - def query(self, query_object: Any, processor: str = ..., result: str = ..., initNs: Optional[Any] = ..., initBindings: Optional[Any] = ..., use_store_provided: bool = ..., **kwargs: Any): ... - def update(self, update_object: Any, processor: str = ..., initNs: Optional[Any] = ..., initBindings: Optional[Any] = ..., use_store_provided: bool = ..., **kwargs: Any): ... - def n3(self): ... - def __reduce__(self): ... - def isomorphic(self, other: Any): ... - def connected(self): ... - def all_nodes(self): ... - def collection(self, identifier: Any): ... - def resource(self, identifier: Any): ... - def skolemize(self, new_graph: Optional[Any] = ..., bnode: Optional[Any] = ...): ... - def de_skolemize(self, new_graph: Optional[Any] = ..., uriref: Optional[Any] = ...): ... - -class ConjunctiveGraph(Graph): - context_aware: bool = ... - default_union: bool = ... - default_context: Any = ... - def __init__(self, store: str = ..., identifier: Optional[Any] = ...) -> None: ... - def __contains__(self, triple_or_quad: Any): ... - def add(self, triple_or_quad: Any) -> None: ... - def addN(self, quads: Any) -> None: ... - def remove(self, triple_or_quad: Any) -> None: ... - def quads(self, triple_or_quad: Optional[Any] = ...) -> None: ... - def triples_choices(self, xxx_todo_changeme4: Any, context: Optional[Any] = ...) -> None: ... - def __len__(self): ... - def contexts(self, triple: Optional[Any] = ...) -> None: ... - def get_context(self, identifier: Any, quoted: bool = ...): ... - def remove_context(self, context: Any) -> None: ... - def context_id(self, uri: Any, context_id: Optional[Any] = ...): ... - def parse(self, source: Optional[Any] = ..., publicID: Optional[Any] = ..., format: Optional[Any] = ..., location: Optional[Any] = ..., file: Optional[Any] = ..., data: Optional[Any] = ..., **args: Any): ... - def __reduce__(self): ... - -class Dataset(ConjunctiveGraph): - __doc__: Any = ... - default_context: Any = ... - default_union: Any = ... - def __init__(self, store: str = ..., default_union: bool = ...) -> None: ... - def graph(self, identifier: Optional[Any] = ...): ... - def parse(self, source: Optional[Any] = ..., publicID: Optional[Any] = ..., format: Optional[Any] = ..., location: Optional[Any] = ..., file: Optional[Any] = ..., data: Optional[Any] = ..., **args: Any): ... - def add_graph(self, g: Any): ... - def remove_graph(self, g: Any) -> None: ... - def contexts(self, triple: Optional[Any] = ...) -> None: ... - graphs: Any = ... - def quads(self, triple_or_quad: Optional[Any] = ...) -> None: ... - -class QuotedGraph(Graph): - def __init__(self, store: Any, identifier: Any) -> None: ... - def add(self, xxx_todo_changeme5: Any) -> None: ... - def addN(self, quads: Any) -> None: ... - def n3(self): ... - def __reduce__(self): ... - -class Seq: - def __init__(self, graph: Any, subject: Any) -> None: ... - def toPython(self): ... - def __iter__(self) -> None: ... - def __len__(self): ... - def __getitem__(self, index: Any): ... - -class ModificationException(Exception): - def __init__(self) -> None: ... - -class UnSupportedAggregateOperation(Exception): - def __init__(self) -> None: ... - -class ReadOnlyGraphAggregate(ConjunctiveGraph): - graphs: Any = ... - def __init__(self, graphs: Any, store: str = ...) -> None: ... - def destroy(self, configuration: Any) -> None: ... - def commit(self) -> None: ... - def rollback(self) -> None: ... - def open(self, configuration: Any, create: bool = ...) -> None: ... - def close(self, commit_pending_transaction: bool = ...) -> None: ... - def add(self, xxx_todo_changeme6: Any) -> None: ... - def addN(self, quads: Any) -> None: ... - def remove(self, xxx_todo_changeme7: Any) -> None: ... - def __contains__(self, triple_or_quad: Any): ... - def quads(self, triple_or_quad: Optional[Any] = ...) -> None: ... - def __len__(self): ... - def __cmp__(self, other: Any): ... - def __iadd__(self, other: Any) -> None: ... - def __isub__(self, other: Any) -> None: ... - def triples_choices(self, xxx_todo_changeme10: Any, context: Optional[Any] = ...) -> None: ... - def qname(self, uri: Any): ... - def compute_qname(self, uri: Any, generate: bool = ...): ... - def bind(self, prefix: Any, namespace: Any, override: bool = ...) -> None: ... - def namespaces(self) -> None: ... - def absolutize(self, uri: Any, defrag: int = ...) -> None: ... - def parse(self, source: Optional[Any] = ..., publicID: Optional[Any] = ..., format: Optional[Any] = ..., location: Optional[Any] = ..., file: Optional[Any] = ..., data: Optional[Any] = ..., **args: Any): ... - def n3(self) -> None: ... diff --git a/typeshed/rdflib/namespace.pyi b/typeshed/rdflib/namespace.pyi deleted file mode 100644 index c0d305f..0000000 --- a/typeshed/rdflib/namespace.pyi +++ /dev/null @@ -1,62 +0,0 @@ -# Stubs for rdflib.namespace (Python 3) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional, Text - -from rdflib.term import URIRef - -class Namespace(str): - __doc__: Any = ... - def __new__(cls, value: Any): ... - @property - def title(self) -> URIRef: ... - def term(self, name: Any) -> URIRef: ... - def __getitem__(self, key: Any, default: Optional[Any] = ...) -> URIRef: ... - def __getattr__(self, name: Any) -> URIRef: ... - -class URIPattern(str): - __doc__: Any = ... - def __new__(cls, value: Any): ... - def __mod__(self, *args: Any, **kwargs: Any): ... - def format(self, *args: Any, **kwargs: Any): ... - -class ClosedNamespace: - uri: Any = ... - def __init__(self, uri: Any, terms: Any) -> None: ... - def term(self, name: Any) -> URIRef: ... - def __getitem__(self, key: Any, default: Optional[Any] = ...) -> URIRef: ... - def __getattr__(self, name: Any) -> URIRef: ... - -class _RDFNamespace(ClosedNamespace): - def __init__(self) -> None: ... - def term(self, name: Any) -> URIRef: ... - -RDF = ClosedNamespace("", []) -RDFS = ClosedNamespace("", []) -OWL = Namespace("") -XSD: Namespace -SKOS: Namespace -DOAP: Namespace -FOAF: Namespace -DC: Namespace -DCTERMS: Namespace -VOID: Namespace - -class NamespaceManager: - graph: Any = ... - def __init__(self, graph: Any) -> None: ... - def reset(self) -> None: ... - store: Any = ... - def qname(self, uri: Any): ... - def normalizeUri(self, rdfTerm: Any): ... - def compute_qname(self, uri: Any, generate: bool = ...): ... - def bind(self, prefix: Any, namespace: Any, override: bool = ..., replace: bool = ...) -> None: ... - def namespaces(self) -> None: ... - def absolutize(self, uri: Any, defrag: int = ...): ... - -def is_ncname(name: Any): ... - -XMLNS: str - -def split_uri(uri: Any): ... diff --git a/typeshed/rdflib/parser.pyi b/typeshed/rdflib/parser.pyi deleted file mode 100644 index fa1ec9a..0000000 --- a/typeshed/rdflib/parser.pyi +++ /dev/null @@ -1,10 +0,0 @@ -# Stubs for rdflib.parser (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from io import StringIO as BytesIO - -class Parser: - def __init__(self): ... - def parse(self, source, sink): ... diff --git a/typeshed/rdflib/plugin.pyi b/typeshed/rdflib/plugin.pyi deleted file mode 100644 index 30026e2..0000000 --- a/typeshed/rdflib/plugin.pyi +++ /dev/null @@ -1,28 +0,0 @@ -# Stubs for rdflib.plugin (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from rdflib.exceptions import Error -from rdflib.parser import Parser - -class PluginException(Error): ... - -class Plugin: - name = ... # type: Any - kind = ... # type: Any - module_path = ... # type: Any - class_name = ... # type: Any - def __init__(self, name, kind, module_path, class_name): ... - def getClass(self): ... - -class PKGPlugin(Plugin): - name = ... # type: Any - kind = ... # type: Any - ep = ... # type: Any - def __init__(self, name, kind, ep): ... - def getClass(self): ... - -def register(name: str, kind: type, module_path: str, class_name: str) -> None: ... -def get(name, kind): ... -def plugins(name=None, kind=None): ... diff --git a/typeshed/rdflib/plugins/parsers/notation3.pyi b/typeshed/rdflib/plugins/parsers/notation3.pyi deleted file mode 100644 index 3177634..0000000 --- a/typeshed/rdflib/plugins/parsers/notation3.pyi +++ /dev/null @@ -1,12 +0,0 @@ -# Stubs for rdflib.plugins.parsers.notation3 (Python 3.5) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from rdflib.parser import Parser - -class BadSyntax(SyntaxError): - lines = ... # type: Any - def __init__(self, uri, lines, argstr, i, why): ... - @property - def message(self): ... diff --git a/typeshed/rdflib/query.pyi b/typeshed/rdflib/query.pyi deleted file mode 100644 index fad3c37..0000000 --- a/typeshed/rdflib/query.pyi +++ /dev/null @@ -1,54 +0,0 @@ -# Stubs for rdflib.query (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from io import StringIO as BytesIO -import collections - -class Processor: - def __init__(self, graph): ... - def query(self, strOrQuery, initBindings=..., initNs=..., DEBUG=False): ... - -class UpdateProcessor: - def __init__(self, graph): ... - def update(self, strOrQuery, initBindings=..., initNs=...): ... - -class ResultException(Exception): ... - -class EncodeOnlyUnicode: - def __init__(self, stream): ... - def write(self, arg): ... - def __getattr__(self, name): ... - -class ResultRow(tuple): - __doc__ = ... # type: Any - def __new__(cls, values, labels): ... - def __getattr__(self, name): ... - def __getitem__(self, name): ... - def asdict(self): ... - -class Result(collections.Iterable): - type = ... # type: Any - vars = ... # type: Any - askAnswer = ... # type: Any - graph = ... # type: Any - def __init__(self, type_): ... - bindings = ... # type: Any - @staticmethod - def parse(source, format='', **kwargs): ... - def serialize(self, destination=None, encoding='', format='', **args): ... - def __len__(self): ... - def __nonzero__(self): ... - def __iter__(self): ... - def __getattr__(self, name): ... - def __eq__(self, other): ... - -class ResultParser: - def __init__(self): ... - def parse(self, source, **kwargs): ... - -class ResultSerializer: - result = ... # type: Any - def __init__(self, result): ... - def serialize(self, stream, encoding='', **kwargs): ... diff --git a/typeshed/rdflib/serializer.pyi b/typeshed/rdflib/serializer.pyi deleted file mode 100644 index a92dac0..0000000 --- a/typeshed/rdflib/serializer.pyi +++ /dev/null @@ -1,13 +0,0 @@ -# Stubs for rdflib.serializer (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any - -class Serializer: - store = ... # type: Any - encoding = ... # type: Any - base = ... # type: Any - def __init__(self, store): ... - def serialize(self, stream, base=None, encoding=None, **args): ... - def relativize(self, uri): ... diff --git a/typeshed/rdflib/store.pyi b/typeshed/rdflib/store.pyi deleted file mode 100644 index 6886321..0000000 --- a/typeshed/rdflib/store.pyi +++ /dev/null @@ -1,48 +0,0 @@ -# Stubs for rdflib.store (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any -from rdflib.events import Event -from io import StringIO as BytesIO - -class StoreCreatedEvent(Event): ... -class TripleAddedEvent(Event): ... -class TripleRemovedEvent(Event): ... - -class NodePickler: - def __init__(self): ... - def register(self, object, id): ... - def loads(self, s): ... - def dumps(self, obj, protocol=None, bin=None): ... - -class Store: - context_aware = ... # type: Any - formula_aware = ... # type: Any - transaction_aware = ... # type: Any - graph_aware = ... # type: Any - dispatcher = ... # type: Any - def __init__(self, configuration=None, identifier=None): ... - node_pickler = ... # type: Any - def create(self, configuration): ... - def open(self, configuration, create=False): ... - def close(self, commit_pending_transaction=False): ... - def destroy(self, configuration): ... - def gc(self): ... - def add(self, __tuple_arg_2, context, quoted=False): ... - def addN(self, quads): ... - def remove(self, __tuple_arg_2, context=None): ... - def triples_choices(self, __tuple_arg_2, context=None): ... - def triples(self, triple_pattern, context=None): ... - def __len__(self, context=None): ... - def contexts(self, triple=None): ... - def query(self, query, initNs, initBindings, queryGraph, **kwargs): ... - def update(self, update, initNs, initBindings, queryGraph, **kwargs): ... - def bind(self, prefix, namespace): ... - def prefix(self, namespace): ... - def namespace(self, prefix): ... - def namespaces(self): ... - def commit(self): ... - def rollback(self): ... - def add_graph(self, graph): ... - def remove_graph(self, graph): ... diff --git a/typeshed/rdflib/term.pyi b/typeshed/rdflib/term.pyi deleted file mode 100644 index 32b09c7..0000000 --- a/typeshed/rdflib/term.pyi +++ /dev/null @@ -1,87 +0,0 @@ -# Stubs for rdflib.term (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Optional - -class Node: ... - -class Identifier(Node, str): - def __new__(cls, value: Any): ... - def eq(self, other: Any): ... - def neq(self, other: Any): ... - def __ne__(self, other: Any): ... - def __eq__(self, other: Any): ... - def __gt__(self, other: Any): ... - def __lt__(self, other: Any): ... - def __le__(self, other: Any): ... - def __ge__(self, other: Any): ... - def __hash__(self): ... - -class URIRef(Identifier): - def __new__(cls, value: Any, base: Optional[Any] = ...): ... - def toPython(self): ... - def n3(self, namespace_manager: Optional[Any] = ...): ... - def defrag(self): ... - def __reduce__(self): ... - def __getnewargs__(self): ... - def __add__(self, other: Any): ... - def __radd__(self, other: Any): ... - def __mod__(self, other: Any): ... - def md5_term_hash(self): ... - def de_skolemize(self): ... - -class Genid(URIRef): ... -class RDFLibGenid(Genid): ... - -class BNode(Identifier): - def __new__(cls, value=None, _sn_gen=..., _prefix=...): ... - def toPython(self): ... - def n3(self, namespace_manager=None): ... - def __getnewargs__(self): ... - def __reduce__(self): ... - def md5_term_hash(self): ... - def skolemize(self, authority=''): ... - -class Literal(Identifier): - __doc__ = ... # type: Any - def __new__(cls, lexical_or_value, lang=None, datatype=None, normalize=None): ... - def normalize(self): ... - @property - def value(self): ... - @property - def language(self): ... - @property - def datatype(self): ... - def __reduce__(self): ... - def __add__(self, val): ... - def __nonzero__(self): ... - def __neg__(self): ... - def __pos__(self): ... - def __abs__(self): ... - def __invert__(self): ... - def __gt__(self, other): ... - def __lt__(self, other): ... - def __le__(self, other): ... - def __ge__(self, other): ... - def __hash__(self): ... - def __eq__(self, other): ... - def eq(self, other): ... - def neq(self, other): ... - def n3(self, namespace_manager=None): ... - def toPython(self): ... - def md5_term_hash(self): ... - -def bind(datatype, pythontype, constructor=None, lexicalizer=None): ... - -class Variable(Identifier): - def __new__(cls, value): ... - def toPython(self): ... - def n3(self, namespace_manager=None): ... - def __reduce__(self): ... - def md5_term_hash(self): ... - -class Statement(Node, tuple): - def __new__(cls, __tuple_arg_2, context): ... - def __reduce__(self): ... - def toPython(self): ... diff --git a/typeshed/rdflib/util.pyi b/typeshed/rdflib/util.pyi deleted file mode 100644 index 0921d30..0000000 --- a/typeshed/rdflib/util.pyi +++ /dev/null @@ -1,21 +0,0 @@ -# Stubs for rdflib.util (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -def list2set(seq): ... -def first(seq): ... -def uniq(sequence, strip=0): ... -def more_than(sequence, number): ... -def to_term(s, default=None): ... -def from_n3(s, default=None, backend=None): ... -def check_context(c): ... -def check_subject(s): ... -def check_predicate(p): ... -def check_object(o): ... -def check_statement(triple): ... -def check_pattern(triple): ... -def date_time(t=None, local_time_zone=False): ... -def parse_date_time(val): ... -def guess_format(fpath, fmap=None): ... -def find_roots(graph, prop, roots=None): ... -def get_tree(graph, root, prop, mapper=..., sortkey=None, done=None, dir=''): ... diff --git a/typeshed/select.pyi b/typeshed/select.pyi deleted file mode 100644 index 094bb91..0000000 --- a/typeshed/select.pyi +++ /dev/null @@ -1,137 +0,0 @@ -import sys -from typing import Any, Optional, Sequence, Tuple, Iterable, List, Union - -# When we have protocols, this should change to a protocol with a fileno method -# See https://docs.python.org/3/c-api/file.html#c.PyObject_AsFileDescriptor -_FileDescriptor = Union[int, Any] - -EPOLLERR: int -EPOLLET: int -EPOLLHUP: int -EPOLLIN: int -EPOLLMSG: int -EPOLLONESHOT: int -EPOLLOUT: int -EPOLLPRI: int -EPOLLRDBAND: int -EPOLLRDNORM: int -EPOLLWRBAND: int -EPOLLWRNORM: int -EPOLL_RDHUP: int -KQ_EV_ADD: int -KQ_EV_CLEAR: int -KQ_EV_DELETE: int -KQ_EV_DISABLE: int -KQ_EV_ENABLE: int -KQ_EV_EOF: int -KQ_EV_ERROR: int -KQ_EV_FLAG1: int -KQ_EV_ONESHOT: int -KQ_EV_SYSFLAGS: int -KQ_FILTER_AIO: int -KQ_FILTER_NETDEV: int -KQ_FILTER_PROC: int -KQ_FILTER_READ: int -KQ_FILTER_SIGNAL: int -KQ_FILTER_TIMER: int -KQ_FILTER_VNODE: int -KQ_FILTER_WRITE: int -KQ_NOTE_ATTRIB: int -KQ_NOTE_CHILD: int -KQ_NOTE_DELETE: int -KQ_NOTE_EXEC: int -KQ_NOTE_EXIT: int -KQ_NOTE_EXTEND: int -KQ_NOTE_FORK: int -KQ_NOTE_LINK: int -KQ_NOTE_LINKDOWN: int -KQ_NOTE_LINKINV: int -KQ_NOTE_LINKUP: int -KQ_NOTE_LOWAT: int -KQ_NOTE_PCTRLMASK: int -KQ_NOTE_PDATAMASK: int -KQ_NOTE_RENAME: int -KQ_NOTE_REVOKE: int -KQ_NOTE_TRACK: int -KQ_NOTE_TRACKERR: int -KQ_NOTE_WRITE: int -PIPE_BUF: int -POLLERR: int -POLLHUP: int -POLLIN: int -POLLMSG: int -POLLNVAL: int -POLLOUT: int -POLLPRI: int -POLLRDBAND: int -POLLRDNORM: int -POLLWRBAND: int -POLLWRNORM: int - -class poll: - def __init__(self) -> None: ... - def register(self, fd: _FileDescriptor, eventmask: int = ...) -> None: ... - def modify(self, fd: _FileDescriptor, eventmask: int) -> None: ... - def unregister(self, fd: _FileDescriptor) -> None: ... - def poll(self, timeout: Optional[float] = ...) -> List[Tuple[int, int]]: ... - -def select(rlist: Sequence[Any], wlist: Sequence[Any], xlist: Sequence[Any], - timeout: Optional[float] = ...) -> Tuple[List[Any], - List[Any], - List[Any]]: ... - -if sys.version_info >= (3, 3): - error = OSError -else: - class error(Exception): ... - -# BSD only -class kevent(object): - data: Any - fflags: int - filter: int - flags: int - ident: int - udata: Any - def __init__(self, ident: _FileDescriptor, filter: int = ..., flags: int = ..., fflags: int = ..., data: Any = ..., udata: Any = ...) -> None: ... - -# BSD only -class kqueue(object): - closed: bool - def __init__(self) -> None: ... - def close(self) -> None: ... - def control(self, changelist: Optional[Iterable[kevent]], max_events: int, timeout: float = ...) -> List[kevent]: ... - def fileno(self) -> int: ... - @classmethod - def fromfd(cls, fd: _FileDescriptor) -> kqueue: ... - -# Linux only -class epoll(object): - if sys.version_info >= (3, 3): - def __init__(self, sizehint: int = ..., flags: int = ...) -> None: ... - else: - def __init__(self, sizehint: int = ...) -> None: ... - if sys.version_info >= (3, 4): - def __enter__(self) -> epoll: ... - def __exit__(self, *args: Any) -> None: ... - def close(self) -> None: ... - closed: bool - def fileno(self) -> int: ... - def register(self, fd: _FileDescriptor, eventmask: int = ...) -> None: ... - def modify(self, fd: _FileDescriptor, eventmask: int) -> None: ... - def unregister(self, fd: _FileDescriptor) -> None: ... - def poll(self, timeout: float = ..., maxevents: int = ...) -> List[Tuple[int, int]]: ... - @classmethod - def fromfd(cls, fd: _FileDescriptor) -> epoll: ... - -if sys.version_info >= (3, 3): - # Solaris only - class devpoll: - if sys.version_info >= (3, 4): - def close(self) -> None: ... - closed: bool - def fileno(self) -> int: ... - def register(self, fd: _FileDescriptor, eventmask: int = ...) -> None: ... - def modify(self, fd: _FileDescriptor, eventmask: int = ...) -> None: ... - def unregister(self, fd: _FileDescriptor) -> None: ... - def poll(self, timeout: Optional[float] = ...) -> List[Tuple[int, int]]: ... \ No newline at end of file diff --git a/typeshed/shellescape/__init__.pyi b/typeshed/shellescape/__init__.pyi deleted file mode 100644 index 621241e..0000000 --- a/typeshed/shellescape/__init__.pyi +++ /dev/null @@ -1,5 +0,0 @@ -# Stubs for shellescape (Python 2) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from .main import quote as quote diff --git a/typeshed/shellescape/main.pyi b/typeshed/shellescape/main.pyi deleted file mode 100644 index 69eade6..0000000 --- a/typeshed/shellescape/main.pyi +++ /dev/null @@ -1,5 +0,0 @@ -# Stubs for shellescape.main (Python 2) - -from typing import AnyStr - -def quote(s: AnyStr) -> AnyStr: ... diff --git a/typeshed/urllib/__init__.py b/typeshed/urllib/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/typeshed/urllib/parse.pyi b/typeshed/urllib/parse.pyi deleted file mode 100644 index cb7837e..0000000 --- a/typeshed/urllib/parse.pyi +++ /dev/null @@ -1,152 +0,0 @@ -# Stubs for urllib.parse -from typing import Any, List, Dict, Tuple, AnyStr, Generic, Iterator, overload, Sequence, Mapping, Union, NamedTuple, Callable, Optional -import sys - -_Str = Union[bytes, str] - - -uses_relative: List[str] -uses_netloc: List[str] -uses_params: List[str] -non_hierarchical: List[str] -uses_query: List[str] -uses_fragment: List[str] -scheme_chars: str -MAX_CACHE_SIZE = 0 - -class _ResultMixinBase(Generic[AnyStr]): - def geturl(https://github.com/self) -> AnyStr: ... - -class _ResultMixinStr(_ResultMixinBase[str]): - def encode(self, encoding: str = ..., errors: str = ...) -> _ResultMixinBytes: ... - - -class _ResultMixinBytes(_ResultMixinBase[str]): - def decode(self, encoding: str = ..., errors: str = ...) -> _ResultMixinStr: ... - - -class _NetlocResultMixinBase(Generic[AnyStr]): - username: AnyStr - password: AnyStr - hostname: AnyStr - port: int - -class _NetlocResultMixinStr(_NetlocResultMixinBase[str], _ResultMixinStr): ... - -class _NetlocResultMixinBytes(_NetlocResultMixinBase[bytes], _ResultMixinBytes): ... - -class _DefragResultBase(Generic[AnyStr]): - url: AnyStr - fragment: AnyStr - @overload - def __getitem__(self, x: slice) -> AnyStr: ... - @overload - def __getitem__(self, x: int) -> AnyStr: ... - def __iter__(self) -> Iterator[AnyStr]: ... - - - -_SplitResultBase = NamedTuple( - '_SplitResultBase', - [ - ('scheme', str), ('netloc', str), ('path', str), ('query', str), ('fragment', str) - ] -) -_SplitResultBytesBase = NamedTuple( - '_SplitResultBytesBase', - [ - ('scheme', bytes), ('netloc', bytes), ('path', bytes), ('query', bytes), ('fragment', bytes) - ] -) - -_ParseResultBase = NamedTuple( - '_ParseResultBase', - [ - ('scheme', str), ('netloc', str), ('path', str), ('params', str), ('query', str), ('fragment', str) - ] -) -_ParseResultBytesBase = NamedTuple( - '_ParseResultBytesBase', - [ - ('scheme', bytes), ('netloc', bytes), ('path', bytes), ('params', bytes), ('query', bytes), ('fragment', bytes) - ] -) - -# Structured result objects for string data -class DefragResult(_DefragResultBase[str], _ResultMixinStr): ... - -class SplitResult(_SplitResultBase, _NetlocResultMixinStr): ... - -class ParseResult(_ParseResultBase, _NetlocResultMixinStr): ... - -# Structured result objects for bytes data -class DefragResultBytes(_DefragResultBase[bytes], _ResultMixinBytes): ... - -class SplitResultBytes(_SplitResultBytesBase, _NetlocResultMixinBytes): ... - -class ParseResultBytes(_ParseResultBytesBase, _NetlocResultMixinBytes): ... - - -def parse_qs(qs: AnyStr, keep_blank_values: bool = ..., strict_parsing: bool = ..., encoding: str = ..., errors: str = ...) -> Dict[AnyStr, List[AnyStr]]: ... - -def parse_qsl(qs: AnyStr, keep_blank_values: bool = ..., strict_parsing: bool = ..., encoding: str = ..., errors: str = ...) -> List[Tuple[AnyStr, AnyStr]]: ... - - -@overload -def quote(string: str, safe: _Str = ..., encoding: str = ..., errors: str = ...) -> str: ... -@overload -def quote(string: bytes, safe: _Str = ...) -> str: ... - -def quote_from_bytes(bs: bytes, safe: _Str = ...) -> str: ... - -@overload -def quote_plus(string: str, safe: _Str = ..., encoding: str = ..., errors: str = ...) -> str: ... -@overload -def quote_plus(string: bytes, safe: _Str = ...) -> str: ... - -def unquote(string: str, encoding: str = ..., errors: str = ...) -> str: ... - -def unquote_to_bytes(string: _Str) -> bytes: ... - -def unquote_plus(string: str, encoding: str = ..., errors: str = ...) -> str: ... - -@overload -def urldefrag(url: str) -> DefragResult: ... -@overload -def urldefrag(url: bytes) -> DefragResultBytes: ... - -if sys.version_info >= (3, 5): - def urlencode(query: Union[Mapping[Any, Any], - Mapping[Any, Sequence[Any]], - Sequence[Tuple[Any, Any]], - Sequence[Tuple[Any, Sequence[Any]]]], - doseq: bool = ..., safe: AnyStr = ..., encoding: str = ..., errors: str = ..., - quote_via: Callable[[str, AnyStr, str, str], str] = ...) -> str: ... -else: - def urlencode(query: Union[Mapping[Any, Any], - Mapping[Any, Sequence[Any]], - Sequence[Tuple[Any, Any]], - Sequence[Tuple[Any, Sequence[Any]]]], - doseq: bool = ..., safe: AnyStr = ..., encoding: str = ..., errors: str = ...) -> str: ... - -def urljoin(base: Optional[AnyStr], url: Optional[AnyStr], allow_fragments: bool = ...) -> AnyStr: ... - -@overload -def urlparse(url: str, scheme: str = ..., allow_fragments: bool = ...) -> ParseResult: ... -@overload -def urlparse(url: bytes, scheme: bytes = ..., allow_fragments: bool = ...) -> ParseResultBytes: ... - -@overload -def urlsplit(url: Optional[str], scheme: str = ..., allow_fragments: bool = ...) -> SplitResult: ... -@overload -def urlsplit(url: bytes, scheme: bytes = ..., allow_fragments: bool = ...) -> SplitResultBytes: ... - -@overload -def urlunparse(components: Tuple[AnyStr, AnyStr, AnyStr, AnyStr, AnyStr, AnyStr]) -> AnyStr: ... -@overload -def urlunparse(components: Sequence[AnyStr]) -> AnyStr: ... - -@overload -def urlunsplit(components: Tuple[AnyStr, AnyStr, AnyStr, AnyStr, AnyStr]) -> AnyStr: ... -@overload -def urlunsplit(components: Sequence[AnyStr]) -> AnyStr: ... diff --git a/typeshed/urllib/subprocess.pyi b/typeshed/urllib/subprocess.pyi deleted file mode 100644 index 2fd8b5b..0000000 --- a/typeshed/urllib/subprocess.pyi +++ /dev/null @@ -1,1208 +0,0 @@ -# Stubs for subprocess - -# Based on http://docs.python.org/3.6/library/subprocess.html -import sys -from typing import Sequence, Any, Mapping, Callable, Tuple, IO, Optional, Union, Type, Text, Generic, TypeVar, AnyStr, overload -from types import TracebackType - -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - -# We prefer to annotate inputs to methods (eg subprocess.check_call) with these -# union types. -# For outputs we use laborious literal based overloads to try to determine -# which specific return types to use, and prefer to fall back to Any when -# this does not work, so the caller does not have to use an assertion to confirm -# which type. -# -# For example: -# -# try: -# x = subprocess.check_output(["ls", "-l"]) -# reveal_type(x) # bytes, based on the overloads -# except TimeoutError as e: -# reveal_type(e.cmd) # Any, but morally is _CMD -_FILE = Union[None, int, IO[Any]] -_TXT = Union[bytes, Text] -if sys.version_info >= (3, 6): - from builtins import _PathLike - _PATH = Union[bytes, Text, _PathLike] -else: - _PATH = Union[bytes, Text] -# Python 3.6 does't support _CMD being a single PathLike. -# See: https://bugs.python.org/issue31961 -_CMD = Union[_TXT, Sequence[_PATH]] -_ENV = Union[Mapping[bytes, _TXT], Mapping[Text, _TXT]] - -_S = TypeVar('_S') -_T = TypeVar('_T') - -class CompletedProcess(Generic[_T]): - # morally: _CMD - args: Any - returncode: int - # These are really both Optional, but requiring checks would be tedious - # and writing all the overloads would be horrific. - stdout: _T - stderr: _T - def __init__(self, args: _CMD, returncode: int, stdout: Optional[_T] = ..., stderr: Optional[_T] = ...) -> None: ... - def check_returncode(self) -> None: ... - -if sys.version_info >= (3, 7): - # Nearly the same args as for 3.6, except for capture_output and text - @overload - def run( - args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - capture_output: bool = ..., - check: bool = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - input: Optional[str] = ..., - text: Literal[True], - timeout: Optional[float] = ..., - ) -> CompletedProcess[str]: ... - @overload - def run( - args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - capture_output: bool = ..., - check: bool = ..., - encoding: str, - errors: Optional[str] = ..., - input: Optional[str] = ..., - text: Optional[bool] = ..., - timeout: Optional[float] = ..., - ) -> CompletedProcess[str]: ... - @overload - def run( - args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - capture_output: bool = ..., - check: bool = ..., - encoding: Optional[str] = ..., - errors: str, - input: Optional[str] = ..., - text: Optional[bool] = ..., - timeout: Optional[float] = ..., - ) -> CompletedProcess[str]: ... - @overload - def run( - args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - *, - universal_newlines: Literal[True], - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - # where the *real* keyword only args start - capture_output: bool = ..., - check: bool = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - input: Optional[str] = ..., - text: Optional[bool] = ..., - timeout: Optional[float] = ..., - ) -> CompletedProcess[str]: ... - @overload - def run( - args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: Literal[False] = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - capture_output: bool = ..., - check: bool = ..., - encoding: None = ..., - errors: None = ..., - input: Optional[bytes] = ..., - text: Literal[None, False] = ..., - timeout: Optional[float] = ..., - ) -> CompletedProcess[bytes]: ... - @overload - def run( - args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - capture_output: bool = ..., - check: bool = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - input: Optional[_TXT] = ..., - text: Optional[bool] = ..., - timeout: Optional[float] = ..., - ) -> CompletedProcess[Any]: ... -elif sys.version_info >= (3, 6): - # Nearly same args as Popen.__init__ except for timeout, input, and check - @overload - def run( - args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - check: bool = ..., - encoding: str, - errors: Optional[str] = ..., - input: Optional[str] = ..., - timeout: Optional[float] = ..., - ) -> CompletedProcess[str]: ... - @overload - def run( - args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - check: bool = ..., - encoding: Optional[str] = ..., - errors: str, - input: Optional[str] = ..., - timeout: Optional[float] = ..., - ) -> CompletedProcess[str]: ... - @overload - def run( - args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - *, - universal_newlines: Literal[True], - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - # where the *real* keyword only args start - check: bool = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - input: Optional[str] = ..., - timeout: Optional[float] = ..., - ) -> CompletedProcess[str]: ... - @overload - def run( - args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: Literal[False] = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - check: bool = ..., - encoding: None = ..., - errors: None = ..., - input: Optional[bytes] = ..., - timeout: Optional[float] = ..., - ) -> CompletedProcess[bytes]: ... - @overload - def run( - args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - check: bool = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - input: Optional[_TXT] = ..., - timeout: Optional[float] = ..., - ) -> CompletedProcess[Any]: ... -else: - # Nearly same args as Popen.__init__ except for timeout, input, and check - @overload - def run( - args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - *, - universal_newlines: Literal[True], - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - # where the *real* keyword only args start - check: bool = ..., - input: Optional[str] = ..., - timeout: Optional[float] = ..., - ) -> CompletedProcess[str]: ... - @overload - def run( - args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: Literal[False] = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - check: bool = ..., - input: Optional[bytes] = ..., - timeout: Optional[float] = ..., - ) -> CompletedProcess[bytes]: ... - @overload - def run( - args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - check: bool = ..., - input: Optional[_TXT] = ..., - timeout: Optional[float] = ..., - ) -> CompletedProcess[Any]: ... - -# Same args as Popen.__init__ -def call(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - timeout: Optional[float] = ...) -> int: ... - -# Same args as Popen.__init__ -def check_call(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - timeout: Optional[float] = ...) -> int: ... - -if sys.version_info >= (3, 7): - # 3.7 added text - @overload - def check_output(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - timeout: Optional[float] = ..., - input: _TXT = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - text: Literal[True], - ) -> str: ... - @overload - def check_output(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - timeout: Optional[float] = ..., - input: _TXT = ..., - encoding: str, - errors: Optional[str] = ..., - text: Optional[bool] = ..., - ) -> str: ... - @overload - def check_output(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - timeout: Optional[float] = ..., - input: _TXT = ..., - encoding: Optional[str] = ..., - errors: str, - text: Optional[bool] = ..., - ) -> str: ... - @overload - def check_output(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - *, - universal_newlines: Literal[True], - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - # where the real keyword only ones start - timeout: Optional[float] = ..., - input: _TXT = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - text: Optional[bool] = ..., - ) -> str: ... - @overload - def check_output(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: Literal[False] = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - timeout: Optional[float] = ..., - input: _TXT = ..., - encoding: None = ..., - errors: None = ..., - text: Literal[None, False] = ..., - ) -> bytes: ... - @overload - def check_output(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - timeout: Optional[float] = ..., - input: _TXT = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - text: Optional[bool] = ..., - ) -> Any: ... # morally: -> _TXT -elif sys.version_info >= (3, 6): - # 3.6 added encoding and errors - @overload - def check_output(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - timeout: Optional[float] = ..., - input: _TXT = ..., - encoding: str, - errors: Optional[str] = ..., - ) -> str: ... - @overload - def check_output(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - timeout: Optional[float] = ..., - input: _TXT = ..., - encoding: Optional[str] = ..., - errors: str, - ) -> str: ... - @overload - def check_output(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - universal_newlines: Literal[True], - timeout: Optional[float] = ..., - input: _TXT = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - ) -> str: ... - @overload - def check_output(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: Literal[False] = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - timeout: Optional[float] = ..., - input: _TXT = ..., - encoding: None = ..., - errors: None = ..., - ) -> bytes: ... - @overload - def check_output(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - timeout: Optional[float] = ..., - input: _TXT = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - ) -> Any: ... # morally: -> _TXT -else: - @overload - def check_output(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - timeout: Optional[float] = ..., - input: _TXT = ..., - *, - universal_newlines: Literal[True], - ) -> str: ... - @overload - def check_output(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: Literal[False] = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - timeout: Optional[float] = ..., - input: _TXT = ..., - ) -> bytes: ... - @overload - def check_output(args: _CMD, - bufsize: int = ..., - executable: _PATH = ..., - stdin: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - timeout: Optional[float] = ..., - input: _TXT = ..., - ) -> Any: ... # morally: -> _TXT - - -PIPE: int -STDOUT: int -DEVNULL: int -class SubprocessError(Exception): ... -class TimeoutExpired(SubprocessError): - def __init__(self, cmd: _CMD, timeout: float, output: Optional[_TXT] = ..., stderr: Optional[_TXT] = ...) -> None: ... - # morally: _CMD - cmd: Any - timeout: float - # morally: Optional[_TXT] - output: Any - stdout: Any - stderr: Any - - -class CalledProcessError(Exception): - returncode: int - # morally: _CMD - cmd: Any - # morally: Optional[_TXT] - output: Any - - # morally: Optional[_TXT] - stdout: Any - stderr: Any - - def __init__(self, - returncode: int, - cmd: _CMD, - output: Optional[_TXT] = ..., - stderr: Optional[_TXT] = ...) -> None: ... - -class Popen(Generic[AnyStr]): - args: _CMD - stdin: IO[AnyStr] - stdout: IO[AnyStr] - stderr: IO[AnyStr] - pid: int - returncode: int - - # Technically it is wrong that Popen provides __new__ instead of __init__ - # but this shouldn't come up hopefully? - - if sys.version_info >= (3, 7): - # text is added in 3.7 - @overload - def __new__(cls, - args: _CMD, - bufsize: int = ..., - executable: Optional[_PATH] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - text: Optional[bool] = ..., - encoding: str, - errors: Optional[str] = ...) -> Popen[str]: ... - @overload - def __new__(cls, - args: _CMD, - bufsize: int = ..., - executable: Optional[_PATH] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - text: Optional[bool] = ..., - encoding: Optional[str] = ..., - errors: str) -> Popen[str]: ... - @overload - def __new__(cls, - args: _CMD, - bufsize: int = ..., - executable: Optional[_PATH] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - *, - universal_newlines: Literal[True], - startupinfo: Optional[Any] = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - # where the *real* keyword only args start - text: Optional[bool] = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ...) -> Popen[str]: ... - @overload - def __new__(cls, - args: _CMD, - bufsize: int = ..., - executable: Optional[_PATH] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - text: Literal[True], - encoding: Optional[str] = ..., - errors: Optional[str] = ...) -> Popen[str]: ... - @overload - def __new__(cls, - args: _CMD, - bufsize: int = ..., - executable: Optional[_PATH] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: Literal[False] = ..., - startupinfo: Optional[Any] = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - text: Literal[None, False] = ..., - encoding: None = ..., - errors: None = ...) -> Popen[bytes]: ... - @overload - def __new__(cls, - args: _CMD, - bufsize: int = ..., - executable: Optional[_PATH] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - text: Optional[bool] = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ...) -> Popen[Any]: ... - elif sys.version_info >= (3, 6): - @overload - def __new__(cls, - args: _CMD, - bufsize: int = ..., - executable: Optional[_PATH] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - encoding: str, - errors: Optional[str] = ...) -> Popen[str]: ... - @overload - def __new__(cls, - args: _CMD, - bufsize: int = ..., - executable: Optional[_PATH] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - encoding: Optional[str] = ..., - errors: str) -> Popen[str]: ... - @overload - def __new__(cls, - args: _CMD, - bufsize: int = ..., - executable: Optional[_PATH] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - *, - universal_newlines: Literal[True], - startupinfo: Optional[Any] = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - # where the *real* keyword only args start - encoding: Optional[str] = ..., - errors: Optional[str] = ...) -> Popen[str]: ... - @overload - def __new__(cls, - args: _CMD, - bufsize: int = ..., - executable: Optional[_PATH] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: Literal[False] = ..., - startupinfo: Optional[Any] = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - encoding: None = ..., - errors: None = ...) -> Popen[bytes]: ... - @overload - def __new__(cls, - args: _CMD, - bufsize: int = ..., - executable: Optional[_PATH] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - encoding: Optional[str] = ..., - errors: Optional[str] = ...) -> Popen[Any]: ... - else: - @overload - def __new__(cls, - args: _CMD, - bufsize: int = ..., - executable: Optional[_PATH] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - *, - universal_newlines: Literal[True], - startupinfo: Optional[Any] = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ...) -> Popen[str]: ... - @overload - def __new__(cls, - args: _CMD, - bufsize: int = ..., - executable: Optional[_PATH] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - *, - universal_newlines: Literal[False] = ..., - startupinfo: Optional[Any] = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ...) -> Popen[bytes]: ... - @overload - def __new__(cls, - args: _CMD, - bufsize: int = ..., - executable: Optional[_PATH] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: Optional[_PATH] = ..., - env: Optional[_ENV] = ..., - universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ...) -> Popen[Any]: ... - - def poll(self) -> int: ... - def wait(self, timeout: Optional[float] = ...) -> int: ... - # Return str/bytes - def communicate(self, - input: Optional[AnyStr] = ..., - timeout: Optional[float] = ..., - # morally this should be optional - ) -> Tuple[AnyStr, AnyStr]: ... - def send_signal(self, signal: int) -> None: ... - def terminate(self) -> None: ... - def kill(self) -> None: ... - def __enter__(self: _S) -> _S: ... - def __exit__(self, type: Optional[Type[BaseException]], value: Optional[BaseException], traceback: Optional[TracebackType]) -> None: ... - -# The result really is always a str. -def getstatusoutput(cmd: _TXT) -> Tuple[int, str]: ... -def getoutput(cmd: _TXT) -> str: ... - -def list2cmdline(seq: Sequence[str]) -> str: ... # undocumented - -if sys.platform == 'win32': - class STARTUPINFO: - if sys.version_info >= (3, 7): - def __init__(self, *, dwFlags: int = ..., hStdInput: Optional[Any] = ..., hStdOutput: Optional[Any] = ..., hStdError: Optional[Any] = ..., wShowWindow: int = ..., lpAttributeList: Optional[Mapping[str, Any]] = ...) -> None: ... - dwFlags: int - hStdInput: Optional[Any] - hStdOutput: Optional[Any] - hStdError: Optional[Any] - wShowWindow: int - if sys.version_info >= (3, 7): - lpAttributeList: Mapping[str, Any] - - STD_INPUT_HANDLE: Any - STD_OUTPUT_HANDLE: Any - STD_ERROR_HANDLE: Any - SW_HIDE: int - STARTF_USESTDHANDLES: int - STARTF_USESHOWWINDOW: int - CREATE_NEW_CONSOLE: int - CREATE_NEW_PROCESS_GROUP: int - if sys.version_info >= (3, 7): - ABOVE_NORMAL_PRIORITY_CLASS: int - BELOW_NORMAL_PRIORITY_CLASS: int - HIGH_PRIORITY_CLASS: int - IDLE_PRIORITY_CLASS: int - NORMAL_PRIORITY_CLASS: int - REALTIME_PRIORITY_CLASS: int - CREATE_NO_WINDOW: int - DETACHED_PROCESS: int - CREATE_DEFAULT_ERROR_MODE: int - CREATE_BREAKAWAY_FROM_JOB: int From 198f4991180a3c2b3ad0243d22067334ebadbf99 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Tue, 27 Sep 2022 11:37:37 +0200 Subject: [PATCH 042/165] update Makefile --- Makefile | 50 +++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index b655cd9..ab41f86 100644 --- a/Makefile +++ b/Makefile @@ -37,36 +37,39 @@ VERSION=2.2.$(shell TZ=UTC git log --first-parent --max-count=1 \ ## all : default task all: dev -## help : print this help message and exit +## help : print this help message and exit help: Makefile @sed -n 's/^##//p' $< -## install-dep : install most of the development dependencies via pip +## cleanup : shortcut for "make sort_imports format flake8 diff_pydocstyle_report" +cleanup: sort_imports format flake8 diff_pydocstyle_report + +## install-dep : install most of the development dependencies via pip install-dep: install-dependencies install-dependencies: FORCE pip install --upgrade $(DEVPKGS) pip install -r requirements.txt -## install-deb-dep: install most of the dev dependencies via apt-get +## install-deb-dep : install most of the dev dependencies via apt-get install-deb-dep: sudo apt-get install $(DEBDEVPKGS) -## install : install the ${MODULE} module and cwltest +## install : install the cwltest package and cwltest script install: FORCE pip install . -## dev : install the ${MODULE} module in dev mode +## dev : install the cwltest package in dev mode dev: install-dep pip install -e . -## dist : create a module package for distribution +## dist : create a module package for distribution dist: dist/${MODULE}-$(VERSION).tar.gz dist/${MODULE}-$(VERSION).tar.gz: $(SOURCES) python setup.py sdist bdist_wheel -## clean : clean up all temporary / machine-generated files +## clean : clean up all temporary / machine-generated files clean: FORCE rm -f ${MODILE}/*.pyc tests/*.pyc python setup.py clean --all || true @@ -74,32 +77,37 @@ clean: FORCE rm -f diff-cover.html # Linting and code style related targets -## sorting imports using isort: https://github.com/timothycrosley/isort -sort_imports: $(PYSOURCES) +## sort_import : sorting imports using isort: https://github.com/timothycrosley/isort +sort_imports: $(PYSOURCES) mypy-stubs isort $^ remove_unused_imports: $(filter-out schema_salad/metaschema.py,$(PYSOURCES)) autoflake --in-place --remove-all-unused-imports $^ pep257: pydocstyle -## pydocstyle : check Python code style +## pydocstyle : check Python docstring style pydocstyle: $(PYSOURCES) pydocstyle --add-ignore=D100,D101,D102,D103 $^ || true pydocstyle_report.txt: $(PYSOURCES) pydocstyle setup.py $^ > $@ 2>&1 || true +## diff_pydocstyle_report : check Python docstring style for changed files only diff_pydocstyle_report: pydocstyle_report.txt diff-quality --compare-branch=main --violations=pydocstyle --fail-under=100 $^ -## format : check/fix all code indentation and formatting (runs black) +## codespell : check for common misspellings +codespell: + codespell -w $(shell git ls-files | grep -v mypy-stubs | grep -v gitignore) + +## format : check/fix all code indentation and formatting (runs black) format: - black setup.py cwltest setup.py + black setup.py cwltest setup.py mypy-stubs format-check: - black --diff --check setup.py cwltest + black --diff --check setup.py cwltest mypy-stubs -## pylint : run static code analysis on Python code +## pylint : run static code analysis on Python code pylint: $(PYSOURCES) pylint --msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}" \ $^ -j0|| true @@ -109,9 +117,9 @@ pylint_report.txt: $(PYSOURCES) $^ -j0> $@ || true diff_pylint_report: pylint_report.txt - diff-quality --violations=pylint pylint_report.txt + diff-quality --compare-branch=main --violations=pylint pylint_report.txt -.coverage: $(PYSOURCES) all +.coverage: $(PYSOURCES) python setup.py test --addopts "--cov --cov-config=.coveragerc --cov-report= ${PYTEST_EXTRA}" coverage.xml: .coverage @@ -127,23 +135,23 @@ coverage-report: .coverage coverage report diff-cover: coverage.xml - diff-cover $^ + diff-cover --compare-branch=main $^ diff-cover.html: coverage.xml - diff-cover $^ --html-report $@ + diff-cover --compare-branch=main $^ --html-report $@ -## test : run the ${MODULE} test suite +## test : run the cwltest test suite test: $(PYSOURCES) all python setup.py test ${PYTEST_EXTRA} -## testcov : run the ${MODULE} test suite and collect coverage +## testcov : run the cwltest test suite and collect coverage testcov: $(PYSOURCES) python setup.py test --addopts "--cov" ${PYTEST_EXTRA} sloccount.sc: $(PYSOURCES) Makefile sloccount --duplicates --wide --details $^ > $@ -## sloccount : count lines of code +## sloccount : count lines of code sloccount: $(PYSOURCES) Makefile sloccount $^ From 9a567b2914d6bc37bad7fae9a9a0b6ad81cc7acf Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Tue, 27 Sep 2022 11:54:25 +0200 Subject: [PATCH 043/165] spellcheck --- .github/workflows/ci-tests.yml | 2 +- Makefile | 2 +- cwltest/__init__.py | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 9ea22be..3fef60a 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -1,4 +1,4 @@ -name: Continous integration tests +name: Continuous integration tests on: push: diff --git a/Makefile b/Makefile index ab41f86..1e84799 100644 --- a/Makefile +++ b/Makefile @@ -182,7 +182,7 @@ pyupgrade: $(filter-out schema_salad/metaschema.py,$(PYSOURCES)) pyupgrade --exit-zero-even-if-changed --py36-plus $^ release-test: FORCE - git diff-index --quiet HEAD -- || ( echo You have uncommited changes, please commit them and try again; false ) + git diff-index --quiet HEAD -- || ( echo You have uncommitted changes, please commit them and try again; false ) ./release-test.sh release: release-test diff --git a/cwltest/__init__.py b/cwltest/__init__.py index e16c828..8f5dbef 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -382,18 +382,18 @@ def arg_parser(): # type: () -> argparse.ArgumentParser def expand_number_range(nr: str) -> List[int]: - ans: List[int] = [] + result: List[int] = [] for s in nr.split(","): sp = s.split("-") if len(sp) == 2: - ans.extend(range(int(sp[0]) - 1, int(sp[1]))) + result.extend(range(int(sp[0]) - 1, int(sp[1]))) else: - ans.append(int(s) - 1) - return ans + result.append(int(s) - 1) + return result -def main(): # type: () -> int - +def main() -> int: + """Run the main logic loop.""" args = arg_parser().parse_args(sys.argv[1:]) if "--" in args.args: args.args.remove("--") @@ -432,7 +432,7 @@ def main(): # type: () -> int suite_name, _ = os.path.splitext(os.path.basename(args.test)) report = junit_xml.TestSuite(suite_name, []) - # the number of total tests, failured tests, unsupported tests and passed tests for each tag + # the number of total tests, failed tests, unsupported tests and passed tests for each tag ntotal = defaultdict(int) # type: Dict[str, int] nfailures = defaultdict(int) # type: Dict[str, int] nunsupported = defaultdict(int) # type: Dict[str, int] From ea68925cb6726c07363a7e5526d9adfd3ffbe23d Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Thu, 29 Sep 2022 14:19:58 +0200 Subject: [PATCH 044/165] start testing with Python 3.11 --- .github/dependabot.yml | 19 ++++++--- .github/workflows/ci-tests.yml | 36 ++++++++++------- README.rst | 2 +- setup.py | 1 + tox.ini | 73 +++++++++++++++------------------- 5 files changed, 71 insertions(+), 60 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 491deae..bf1d70a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,7 +1,16 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + version: 2 updates: -- package-ecosystem: pip - directory: "/" - schedule: - interval: daily - open-pull-requests-limit: 10 + - package-ecosystem: "pip" + directory: "/" # Location of package manifests + schedule: + interval: "daily" + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 3fef60a..03d7c3b 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -15,13 +15,13 @@ jobs: tox: name: CI tests via Tox - runs-on: ubuntu-20.04 + runs-on: ubuntu-20.04 # 22.04 doesn't support Python 3.6 strategy: matrix: # The README.rst file mentions the versions tested, please update it as well py-ver-major: [3] - py-ver-minor: [6, 7, 8, 9, 10] + py-ver-minor: [6, 7, 8, 9, 10, 11] step: [lint, unit, mypy] exclude: - py-ver-major: 3 @@ -33,15 +33,23 @@ jobs: TOXENV: ${{ format('py{0}{1}-{2}', matrix.py-ver-major, matrix.py-ver-minor, matrix.step) }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v2 + if: matrix.py-ver-minor != 11 + uses: actions/setup-python@v4 with: python-version: ${{ env.py-semver }} + - name: Set up Python 3.11.0-rc.2 + if: matrix.py-ver-minor == 11 + uses: actions/setup-python@v4 + with: + python-version: 3.11.0-rc.2 + + - name: Cache for pip - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ matrix.step }}-${{ hashFiles('requirements.txt', 'tox.ini') }} @@ -53,7 +61,7 @@ jobs: - name: MyPy cache if: ${{ matrix.step == 'mypy' }} - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: .mypy_cache/${{ env.py-semver }} key: mypy-${{ env.py-semver }} @@ -63,7 +71,7 @@ jobs: - name: Upload coverage to Codecov if: ${{ matrix.step == 'unit' }} - uses: codecov/codecov-action@v2.1.0 + uses: codecov/codecov-action@v3 with: fail_ci_if_error: true @@ -81,17 +89,17 @@ jobs: TOXENV: ${{ format('py310-{0}', matrix.step) }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ env.py-semver }} - name: Cache for pip - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ matrix.step }}-${{ hashFiles('requirements.txt') }} @@ -111,18 +119,18 @@ jobs: release_test: name: cwltest release test - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: "3.10" # quoted, otherwise that turns into the number 3.1 - name: Cache for pip - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-release-${{ hashFiles('requirements.txt', 'test-requirements.txt') }} diff --git a/README.rst b/README.rst index e93d862..15066a6 100644 --- a/README.rst +++ b/README.rst @@ -32,7 +32,7 @@ This is a testing tool for checking the output of Tools and Workflows described with the Common Workflow Language. Among other uses, it is used to run the CWL conformance tests. -This is written and tested for Python 3.6, 3.7, 3.8, 3.9, and 3.10. +This is written and tested for Python 3.6, 3.7, 3.8, 3.9, 3.10, and 3.11. Install ------- diff --git a/setup.py b/setup.py index 445d543..6466981 100644 --- a/setup.py +++ b/setup.py @@ -62,6 +62,7 @@ "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Typing :: Typed", ], ) diff --git a/tox.ini b/tox.ini index 430d084..37b83b3 100644 --- a/tox.ini +++ b/tox.ini @@ -1,12 +1,11 @@ [tox] envlist = - py{36,37,38,39,310}-lint, - py{36,37,38,39,310}-unit, - py{36,37,38,39,310}-bandit, - py{37,38,39,310}-mypy, - py39-pipconflictchecker, - py39-lintreadme, - py39-pydocstyle + py{36,37,38,39,310,311}-lint, + py{36,37,38,39,310,311}-unit, + py{36,37,38,39,310,311}-bandit, + py{37,38,39,310,311}-mypy, + py310-lintreadme, + py310-pydocstyle skip_missing_interpreters = True @@ -21,50 +20,51 @@ python = 3.8: py38 3.9: py39 3.10: py310 + 3.11: py311 [testenv] description = - py{36,37,38,39,310}-unit: Run the unit tests - py{36,37,38,39,310}-lint: Lint the Python code - py{36,37,38,39,310}-bandit: Search for common security issues - py{37,38,39,310}-mypy: Check for type safety - py39-pydocstyle: docstring style checker - py39-lintreadme: Lint the README.rst->.md conversion + py{36,37,38,39,310,311}-unit: Run the unit tests + py{36,37,38,39,310,311}-lint: Lint the Python code + py{36,37,38,39,310,311}-bandit: Search for common security issues + py{37,38,39,310,311}-mypy: Check for type safety + py310-pydocstyle: docstring style checker + py310-lintreadme: Lint the README.rst->.md conversion passenv = CI GITHUB_* deps = - py{36,37,38,39,310}-{unit,mypy}: -rrequirements.txt - py{36,37,38,39,310}-{unit,mypy}: -rtest-requirements.txt - py{36,37,38,39,310}-lint: flake8-bugbear - py{36,37,38,39,310}-lint: black - py{36,37,38,39,310}-bandit: bandit - py{37,38,39,310}-mypy: -rmypy-requirements.txt + py{36,37,38,39,310,311}-{unit,mypy}: -rrequirements.txt + py{36,37,38,39,310,311}-{unit,mypy}: -rtest-requirements.txt + py{36,37,38,39,310,311}-lint: flake8-bugbear + py{36,37,38,39,310,311}-lint: black + py{36,37,38,39,310,311}-bandit: bandit + py{37,38,39,310,311}-mypy: -rmypy-requirements.txt setenv = - py{36,37,38,39,310}-unit: LC_ALL = C.UTF-8 + py{36,37,38,39,310,311}-unit: LC_ALL = C.UTF-8 commands = - py{36,37,38,39,310}-unit: python -m pip install -U pip setuptools wheel - py{36,37,38,39,310}-unit: make coverage-report coverage.xml PYTEST_EXTRA={posargs} - py{36,37,38,39,310}-bandit: bandit --recursive cwltest --exclude cwltest/tests/* - py{36,37,38,39,310}-lint: make flake8 - py{36,37,38,39,310}-lint: make format-check - py{37,38,39,310}-mypy: make mypy + py{36,37,38,39,310,311}-unit: python -m pip install -U pip setuptools wheel + py{36,37,38,39,310,311}-unit: make coverage-report coverage.xml PYTEST_EXTRA={posargs} + py{36,37,38,39,310,311}-bandit: bandit --recursive cwltest --exclude cwltest/tests/* + py{36,37,38,39,310,311}-lint: make flake8 + py{36,37,38,39,310,311}-lint: make format-check + py{37,38,39,310,311}-mypy: make mypy py37-mypy: make mypy_3.6 whitelist_externals = - py{36,37,38,39,310}-lint: flake8 - py{36,37,38,39,310}-lint: black - py{36,37,38,39,310}-{mypy,shellcheck,lint,unit}: make + py{36,37,38,39,310,311}-lint: flake8 + py{36,37,38,39,310,311}-lint: black + py{36,37,38,39,310,311}-{mypy,shellcheck,lint,unit}: make skip_install = - py{36,37,38,39,310}-lint: true - py{36,37,38,39,310}-bandit: true + py{36,37,38,39,310,311}-lint: true + py{36,37,38,39,310,311}-bandit: true -[testenv:py39-pydocstyle] +[testenv:py310-pydocstyle] whitelist_externals = make commands = make diff_pydocstyle_report deps = @@ -72,14 +72,7 @@ deps = diff-cover skip_install = true -[testenv:py39-pipconflictchecker] -commands = pipconflictchecker -whitelist_externals = pipconflictchecker -deps = - pip-conflict-checker - pip==9.0.3 - -[testenv:py39-lintreadme] +[testenv:py310-lintreadme] description = Lint the README.rst->.md conversion commands = python setup.py sdist From c0f8224097ab67c15ba8fd680a2cfef77628da6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Sep 2022 12:31:51 +0000 Subject: [PATCH 045/165] Bump github/codeql-action from 1 to 2 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 1 to 2. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v1...v2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 3cd36ce..b88bbd0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -26,9 +26,9 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: python - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 From c73bd305ba00a406df3bddbaf5111cf239e9d2ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Sep 2022 12:43:49 +0000 Subject: [PATCH 046/165] Bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index b88bbd0..7993d84 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. From 36040848655cd6b6597c4a6350f08270ed97f402 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Oct 2022 00:11:23 +0000 Subject: [PATCH 047/165] Bump mypy from 0.981 to 0.982 Bumps [mypy](https://github.com/python/mypy) from 0.981 to 0.982. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.981...v0.982) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 7678736..f04612c 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,3 +1,3 @@ -mypy==0.981 +mypy==0.982 types-setuptools types-requests From e3eae1aa1dae2fb8db51d595b13620753fd11b5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Oct 2022 00:18:26 +0000 Subject: [PATCH 048/165] Update pytest requirement from <7.2,>=6.2 to >=6.2,<7.3 Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/6.2.0...7.2.0) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 072f0cc..e5540ed 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,2 +1,2 @@ -pytest >= 6.2, < 7.2 +pytest >= 6.2, < 7.3 pytest-cov From cc6caeb6d45fdeba753244feea6623a38cbb7da2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Nov 2022 09:48:33 +0100 Subject: [PATCH 049/165] Bump mypy from 0.982 to 0.990 (#153) * Bump mypy from 0.982 to 0.990 Bumps [mypy](https://github.com/python/mypy) from 0.982 to 0.990. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.982...v0.990) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * mypy 0.990 needs this override Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Michael R. Crusoe --- mypy-requirements.txt | 2 +- mypy-stubs/rdflib/namespace/__init__.pyi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index f04612c..05121dd 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,3 +1,3 @@ -mypy==0.982 +mypy==0.990 types-setuptools types-requests diff --git a/mypy-stubs/rdflib/namespace/__init__.pyi b/mypy-stubs/rdflib/namespace/__init__.pyi index e5342fd..63af929 100644 --- a/mypy-stubs/rdflib/namespace/__init__.pyi +++ b/mypy-stubs/rdflib/namespace/__init__.pyi @@ -33,7 +33,7 @@ __all__ = [ class Namespace(str): @property - def title(self) -> URIRef: ... + def title(self) -> URIRef: ... # type: ignore[override] def term(self, name: Any) -> URIRef: ... def __getitem__(self, key: Any) -> URIRef: ... def __getattr__(self, name: str) -> URIRef: ... From 220dfb6de68afee82a5bad0ca563f0b190de4e85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Nov 2022 09:24:29 +0100 Subject: [PATCH 050/165] Bump mypy from 0.990 to 0.991 (#154) Bumps [mypy](https://github.com/python/mypy) from 0.990 to 0.991. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.990...v0.991) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 05121dd..f620fb9 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,3 +1,3 @@ -mypy==0.990 +mypy==0.991 types-setuptools types-requests From 0ce17ac5a963cb80873aa5e967f401080061a1a9 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" <1330696+mr-c@users.noreply.github.com> Date: Wed, 7 Dec 2022 08:58:13 +0100 Subject: [PATCH 051/165] remove redundant comparison --- cwltest/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cwltest/__init__.py b/cwltest/__init__.py index 8f5dbef..c0e58ad 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -567,7 +567,7 @@ def main() -> int: passed += 1 for t in tags: npassed[t] += 1 - elif return_code != 0 and return_code != UNSUPPORTED_FEATURE: + elif return_code != UNSUPPORTED_FEATURE: failures += 1 for t in tags: nfailures[t] += 1 From 80ec2a34da15d860f83836dfd5f50d6085804699 Mon Sep 17 00:00:00 2001 From: Iacopo Colonnelli Date: Wed, 4 Jan 2023 10:11:09 +0100 Subject: [PATCH 052/165] Code reorganization (#155) This commit improves code organization by extracting functionalities from the `__init__.py` file and dividing them into more specialized Python modules. In particular: - An `argparser.py` module contains the argument parser for the cwltest CLI - A `main.py` module contains the code to run the tests - A `__main__.py` file serves as the main entrypoint for the package - Some logic has been moved from the `__init__.py` file to the `utils.py` module * CI: test with Python 3.11 final, bandit Co-authored-by: Michael R. Crusoe --- .github/workflows/ci-tests.yml | 10 +- cwltest/__init__.py | 638 +------------------------- cwltest/__main__.py | 5 + cwltest/argparser.py | 114 +++++ cwltest/main.py | 458 ++++++++++++++++++ cwltest/tests/test_argparse.py | 2 +- cwltest/tests/test_categories.py | 2 +- cwltest/tests/test_compare.py | 3 +- cwltest/tests/test_exclude_tags.py | 5 +- cwltest/tests/test_integer_id.py | 7 +- cwltest/tests/test_multi_lined_doc.py | 5 +- cwltest/tests/test_prepare.py | 5 +- cwltest/tests/test_short_names.py | 4 +- cwltest/tests/test_string_id.py | 5 +- cwltest/tests/test_timeout.py | 10 +- cwltest/utils.py | 69 ++- setup.py | 2 +- tox.ini | 4 +- 18 files changed, 669 insertions(+), 679 deletions(-) create mode 100644 cwltest/__main__.py create mode 100644 cwltest/argparser.py create mode 100644 cwltest/main.py diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 03d7c3b..3738b7b 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -22,7 +22,7 @@ jobs: # The README.rst file mentions the versions tested, please update it as well py-ver-major: [3] py-ver-minor: [6, 7, 8, 9, 10, 11] - step: [lint, unit, mypy] + step: [lint, unit, mypy, bandit] exclude: - py-ver-major: 3 py-ver-minor: 6 @@ -36,18 +36,10 @@ jobs: - uses: actions/checkout@v3 - name: Set up Python - if: matrix.py-ver-minor != 11 uses: actions/setup-python@v4 with: python-version: ${{ env.py-semver }} - - name: Set up Python 3.11.0-rc.2 - if: matrix.py-ver-minor == 11 - uses: actions/setup-python@v4 - with: - python-version: 3.11.0-rc.2 - - - name: Cache for pip uses: actions/cache@v3 with: diff --git a/cwltest/__init__.py b/cwltest/__init__.py index c0e58ad..5b6419f 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -1,640 +1,14 @@ -#!/usr/bin/env python +"""Common Workflow Language testing framework.""" -import argparse -import json import logging -import os -import re -import shutil -import subprocess # nosec -import sys -import tempfile import threading -import time -from collections import defaultdict -from concurrent.futures import ThreadPoolExecutor -from shlex import quote -from typing import Any, Dict, List, Optional, Set, Union - -import junit_xml -import pkg_resources # part of setuptools -import ruamel.yaml.scanner as yamlscanner -import schema_salad.avro.schema -import schema_salad.ref_resolver -import schema_salad.schema -from rdflib import Graph - -from cwltest.utils import ( - REQUIRED, - CompareFail, - TestResult, - compare, - get_test_number_by_key, -) - -_logger = logging.getLogger("cwltest") -_logger.addHandler(logging.StreamHandler()) -_logger.setLevel(logging.INFO) UNSUPPORTED_FEATURE = 33 DEFAULT_TIMEOUT = 600 # 10 minutes +REQUIRED = "required" -templock = threading.Lock() - - -def shortname( - name, # type: str -): # type: (...) -> str - """ - Return the short name of a given name. - It is a workaround of https://github.com/common-workflow-language/schema_salad/issues/511. - """ - return [n for n in re.split("[/#]", name) if len(n)][-1] - - -def prepare_test_command( - tool, # type: str - args, # type: List[str] - testargs, # type: Optional[List[str]] - test, # type: Dict[str, str] - cwd, # type: str - verbose=False, # type: bool -): # type: (...) -> List[str] - """Turn the test into a command line.""" - test_command = [tool] - test_command.extend(args) - - # Add additional arguments given in test case - if testargs is not None: - for testarg in testargs: - (test_case_name, prefix) = testarg.split("==") - if test_case_name in test: - test_command.extend([prefix, test[test_case_name]]) - - # Add prefixes if running on MacOSX so that boot2docker writes to /Users - with templock: - if "darwin" in sys.platform and tool.endswith("cwltool"): - outdir = tempfile.mkdtemp(prefix=os.path.abspath(os.path.curdir)) - test_command.extend( - [ - f"--tmp-outdir-prefix={outdir}", - f"--tmpdir-prefix={outdir}", - ] - ) - else: - outdir = tempfile.mkdtemp() - test_command.extend([f"--outdir={outdir}"]) - if not verbose: - test_command.extend(["--quiet"]) - - cwd = schema_salad.ref_resolver.file_uri(cwd) - toolpath = test["tool"] - if toolpath.startswith(cwd): - toolpath = toolpath[len(cwd) + 1 :] - test_command.extend([os.path.normcase(toolpath)]) - - jobpath = test.get("job") - if jobpath: - if jobpath.startswith(cwd): - jobpath = jobpath[len(cwd) + 1 :] - test_command.append(os.path.normcase(jobpath)) - return test_command - - -def run_test( - args, # type: argparse.Namespace - test, # type: Dict[str, str] - test_number, # type: int - total_tests, # type: int - timeout, # type: int - junit_verbose=False, # type: bool - verbose=False, # type: bool -): # type: (...) -> TestResult - - global templock - - out = {} # type: Dict[str,Any] - outdir = outstr = outerr = "" - test_command = [] # type: List[str] - duration = 0.0 - prefix = "" - suffix = "" - if sys.stderr.isatty(): - prefix = "\r" - else: - suffix = "\n" - try: - process = None # type: Optional[subprocess.Popen[str]] - cwd = os.getcwd() - test_command = prepare_test_command( - args.tool, args.args, args.testargs, test, cwd, junit_verbose - ) - - if test.get("short_name"): - sys.stderr.write( - "%sTest [%i/%i] %s: %s%s\n" - % ( - prefix, - test_number, - total_tests, - test.get("short_name"), - test.get("doc", "").replace("\n", " ").strip(), - suffix, - ) - ) - else: - sys.stderr.write( - "%sTest [%i/%i] %s%s\n" - % ( - prefix, - test_number, - total_tests, - test.get("doc", "").replace("\n", " ").strip(), - suffix, - ) - ) - if verbose: - sys.stderr.write(f"Running: {' '.join(test_command)}\n") - sys.stderr.flush() - - start_time = time.time() - stderr = subprocess.PIPE if not args.verbose else None - process = subprocess.Popen( # nosec - test_command, - stdout=subprocess.PIPE, - stderr=stderr, - universal_newlines=True, - cwd=cwd, - ) - outstr, outerr = process.communicate(timeout=timeout) - return_code = process.poll() - duration = time.time() - start_time - if return_code: - raise subprocess.CalledProcessError(return_code, " ".join(test_command)) - - out = json.loads(outstr) - except ValueError as err: - _logger.error(str(err)) - _logger.error(outstr) - _logger.error(outerr) - except subprocess.CalledProcessError as err: - if err.returncode == UNSUPPORTED_FEATURE and REQUIRED not in test.get( - "tags", ["required"] - ): - return TestResult( - UNSUPPORTED_FEATURE, outstr, outerr, duration, args.classname - ) - if test.get("should_fail", False): - return TestResult(0, outstr, outerr, duration, args.classname) - _logger.error( - """Test %i failed: %s""", - test_number, - " ".join([quote(tc) for tc in test_command]), - ) - _logger.error(test.get("doc", "").replace("\n", " ").strip()) - if err.returncode == UNSUPPORTED_FEATURE: - _logger.error("Does not support required feature") - else: - _logger.error("Returned non-zero") - _logger.error(outerr) - return TestResult(1, outstr, outerr, duration, args.classname, str(err)) - except (yamlscanner.ScannerError, TypeError) as err: - _logger.error( - """Test %i failed: %s""", - test_number, - " ".join([quote(tc) for tc in test_command]), - ) - _logger.error(outstr) - _logger.error("Parse error %s", str(err)) - _logger.error(outerr) - except KeyboardInterrupt: - _logger.error( - """Test %i interrupted: %s""", - test_number, - " ".join([quote(tc) for tc in test_command]), - ) - raise - except subprocess.TimeoutExpired: - _logger.error( - """Test %i timed out: %s""", - test_number, - " ".join([quote(tc) for tc in test_command]), - ) - _logger.error(test.get("doc", "").replace("\n", " ").strip()) - # Kill and re-communicate to get the logs and reap the child, as - # instructed in the subprocess docs. - if process: - process.kill() - outstr, outerr = process.communicate() - return TestResult(2, outstr, outerr, timeout, args.classname, "Test timed out") - finally: - if process is not None and process.returncode is None: - _logger.error("""Terminating lingering process""") - process.terminate() - for _ in range(0, 3): - time.sleep(1) - if process.poll() is not None: - break - if process.returncode is None: - process.kill() - - fail_message = "" - - if test.get("should_fail", False): - _logger.warning( - """Test %i failed: %s""", - test_number, - " ".join([quote(tc) for tc in test_command]), - ) - _logger.warning(test.get("doc", "").replace("\n", " ").strip()) - _logger.warning("Returned zero but it should be non-zero") - return TestResult(1, outstr, outerr, duration, args.classname) - - try: - compare(test.get("output"), out) - except CompareFail as ex: - _logger.warning( - """Test %i failed: %s""", - test_number, - " ".join([quote(tc) for tc in test_command]), - ) - _logger.warning(test.get("doc", "").replace("\n", " ").strip()) - _logger.warning("Compare failure %s", ex) - fail_message = str(ex) - - if outdir: - shutil.rmtree(outdir, True) - - return TestResult( - (1 if fail_message else 0), - outstr, - outerr, - duration, - args.classname, - fail_message, - ) - - -def arg_parser(): # type: () -> argparse.ArgumentParser - parser = argparse.ArgumentParser( - description="Common Workflow Language testing framework" - ) - parser.add_argument( - "--test", type=str, help="YAML file describing test cases", required=True - ) - parser.add_argument( - "--basedir", type=str, help="Basedir to use for tests", default="." - ) - parser.add_argument("-l", action="https://github.com/store_true", help="List tests then exit") - parser.add_argument( - "-n", type=str, default=None, help="Run specific tests, format is 1,3-6,9" - ) - parser.add_argument( - "-s", - type=str, - default=None, - help="Run specific tests using their short names separated by comma", - ) - parser.add_argument( - "-N", - type=str, - default=None, - help="Exclude specific tests by number, format is 1,3-6,9", - ) - parser.add_argument( - "-S", - type=str, - default=None, - help="Exclude specific tests by short names separated by comma", - ) - parser.add_argument( - "--tool", - type=str, - default="cwl-runner", - help="CWL runner executable to use (default 'cwl-runner'", - ) - parser.add_argument( - "--only-tools", action="https://github.com/store_true", help="Only test CommandLineTools" - ) - parser.add_argument("--tags", type=str, default=None, help="Tags to be tested") - parser.add_argument( - "--exclude-tags", type=str, default=None, help="Tags not to be tested" - ) - parser.add_argument("--show-tags", action="https://github.com/store_true", help="Show all Tags.") - parser.add_argument( - "--junit-xml", type=str, default=None, help="Path to JUnit xml file" - ) - parser.add_argument( - "--junit-verbose", - action="https://github.com/store_true", - help="Store more verbose output to JUnit xml file", - ) - parser.add_argument( - "--test-arg", - type=str, - help="Additional argument " - "given in test cases and required prefix for tool runner.", - default=None, - metavar="cache==--cache-dir", - action="https://github.com/append", - dest="testargs", - ) - parser.add_argument( - "args", help="arguments to pass first to tool runner", nargs=argparse.REMAINDER - ) - parser.add_argument( - "-j", - type=int, - default=1, - help="Specifies the number of tests to run simultaneously " - "(defaults to one).", - ) - parser.add_argument( - "--verbose", action="https://github.com/store_true", help="More verbose output during test run." - ) - parser.add_argument( - "--classname", - type=str, - default="", - help="Specify classname for the Test Suite.", - ) - parser.add_argument( - "--timeout", - type=int, - default=DEFAULT_TIMEOUT, - help="Time of execution in seconds after which the test will be " - "skipped. Defaults to {} seconds ({} minutes).".format( - DEFAULT_TIMEOUT, DEFAULT_TIMEOUT / 60 - ), - ) - parser.add_argument( - "--badgedir", type=str, help="Directory that stores JSON files for badges." - ) - - pkg = pkg_resources.require("cwltest") - if pkg: - ver = f"{sys.argv[0]} {pkg[0].version}" - else: - ver = "{} {}".format(sys.argv[0], "unknown version") - parser.add_argument("--version", action="https://github.com/version", version=ver) - - return parser - +logger = logging.getLogger("cwltest") +logger.addHandler(logging.StreamHandler()) +logger.setLevel(logging.INFO) -def expand_number_range(nr: str) -> List[int]: - result: List[int] = [] - for s in nr.split(","): - sp = s.split("-") - if len(sp) == 2: - result.extend(range(int(sp[0]) - 1, int(sp[1]))) - else: - result.append(int(s) - 1) - return result - - -def main() -> int: - """Run the main logic loop.""" - args = arg_parser().parse_args(sys.argv[1:]) - if "--" in args.args: - args.args.remove("--") - - # Remove test arguments with wrong syntax - if args.testargs is not None: - args.testargs = [ - testarg for testarg in args.testargs if testarg.count("==") == 1 - ] - - if not args.test: - arg_parser().print_help() - return 1 - - schema_resource = pkg_resources.resource_stream(__name__, "cwltest-schema.yml") - cache = { - "https://w3id.org/cwl/cwltest/cwltest-schema.yml": schema_resource.read().decode( - "utf-8" - ) - } # type: Optional[Dict[str, Union[str, Graph, bool]]] - (document_loader, avsc_names, _, _,) = schema_salad.schema.load_schema( - "https://w3id.org/cwl/cwltest/cwltest-schema.yml", cache=cache - ) - - if not isinstance(avsc_names, schema_salad.avro.schema.Names): - print(avsc_names) - return 1 - - tests, metadata = schema_salad.schema.load_and_validate( - document_loader, avsc_names, args.test, True - ) - - failures = 0 - unsupported = 0 - passed = 0 - suite_name, _ = os.path.splitext(os.path.basename(args.test)) - report = junit_xml.TestSuite(suite_name, []) - - # the number of total tests, failed tests, unsupported tests and passed tests for each tag - ntotal = defaultdict(int) # type: Dict[str, int] - nfailures = defaultdict(int) # type: Dict[str, int] - nunsupported = defaultdict(int) # type: Dict[str, int] - npassed = defaultdict(int) # type: Dict[str, int] - - if args.only_tools: - alltests = tests - tests = [] - for t in alltests: - loader = schema_salad.ref_resolver.Loader({"id": "@id"}) - cwl = loader.resolve_ref(t["tool"])[0] - if isinstance(cwl, dict): - if cwl["class"] == "CommandLineTool": - tests.append(t) - else: - raise Exception("Unexpected code path.") - - if args.tags: - alltests = tests - tests = [] - tags = args.tags.split(",") - for t in alltests: - ts = t.get("tags", []) - if any(tag in ts for tag in tags): - tests.append(t) - - if args.exclude_tags: - ex_tests = [] - tags = args.exclude_tags.split(",") - for t in tests: - ts = t.get("tags", []) - if all(tag not in ts for tag in tags): - ex_tests.append(t) - tests = ex_tests - - for t in tests: - if t.get("label"): - _logger.warning("The `label` field is deprecated. Use `id` field instead.") - t["short_name"] = t["label"] - elif t.get("id"): - if isinstance(t.get("id"), str): - t["short_name"] = shortname(t["id"]) - else: - _logger.warning( - "The `id` field with integer is deprecated. Use string identifier instead." - ) - else: - _logger.warning("The `id` field is missing.") - - if args.show_tags: - alltags = set() # type: Set[str] - for t in tests: - ts = t.get("tags", []) - alltags |= set(ts) - for tag in alltags: - print(tag) - return 0 - - if args.l: - for i, t in enumerate(tests): - if t.get("short_name"): - print( - "[%i] %s: %s" - % ( - i + 1, - t["short_name"], - t.get("doc", "").replace("\n", " ").strip(), - ) - ) - else: - print("[%i] %s" % (i + 1, t.get("doc", "").replace("\n", " ").strip())) - - return 0 - - if args.n is not None or args.s is not None: - ntest = [] - if args.n is not None: - ntest = expand_number_range(args.n) - if args.s is not None: - for s in args.s.split(","): - test_number = get_test_number_by_key(tests, "short_name", s) - if test_number: - ntest.append(test_number) - else: - _logger.error('Test with short name "%s" not found ', s) - return 1 - else: - ntest = list(range(0, len(tests))) - - exclude_n = [] - if args.N is not None: - exclude_n = expand_number_range(args.N) - if args.S is not None: - for s in args.S.split(","): - test_number = get_test_number_by_key(tests, "short_name", s) - if test_number: - exclude_n.append(test_number) - else: - _logger.error('Test with short name "%s" not found ', s) - return 1 - - ntest = list(filter(lambda x: x not in exclude_n, ntest)) - - total = 0 - with ThreadPoolExecutor(max_workers=args.j) as executor: - jobs = [ - executor.submit( - run_test, - args, - tests[i], - i + 1, - len(tests), - args.timeout, - args.junit_verbose, - args.verbose, - ) - for i in ntest - ] - try: - for i, job in zip(ntest, jobs): - test_result = job.result() - test_case = test_result.create_test_case(tests[i]) - test_case.url = f"cwltest:{suite_name}#{i + 1}" - total += 1 - tags = tests[i].get("tags", []) - for t in tags: - ntotal[t] += 1 - - return_code = test_result.return_code - category = test_case.category - if return_code == 0: - passed += 1 - for t in tags: - npassed[t] += 1 - elif return_code != UNSUPPORTED_FEATURE: - failures += 1 - for t in tags: - nfailures[t] += 1 - test_case.add_failure_info(output=test_result.message) - elif return_code == UNSUPPORTED_FEATURE and category == REQUIRED: - failures += 1 - for t in tags: - nfailures[t] += 1 - test_case.add_failure_info(output=test_result.message) - elif category != REQUIRED and return_code == UNSUPPORTED_FEATURE: - unsupported += 1 - for t in tags: - nunsupported[t] += 1 - test_case.add_skipped_info("Unsupported") - else: - raise Exception( - "This is impossible, return_code: {}, category: " - "{}".format(return_code, category) - ) - report.test_cases.append(test_case) - except KeyboardInterrupt: - for job in jobs: - job.cancel() - _logger.error("Tests interrupted") - - if args.junit_xml: - with open(args.junit_xml, "w") as xml: - junit_xml.to_xml_report_file(xml, [report]) - - if args.badgedir: - os.mkdir(args.badgedir) - for t, v in ntotal.items(): - percent = int((npassed[t] / float(v)) * 100) - if npassed[t] == v: - color = "green" - elif t == "required": - color = "red" - else: - color = "yellow" - - with open(f"{args.badgedir}/{t}.json", "w") as out: - out.write( - json.dumps( - { - "subject": f"{t}", - "status": f"{percent}%", - "color": color, - } - ) - ) - - if failures == 0 and unsupported == 0: - _logger.info("All tests passed") - return 0 - if failures == 0 and unsupported > 0: - _logger.warning( - "%i tests passed, %i unsupported features", total - unsupported, unsupported - ) - return 0 - _logger.warning( - "%i tests passed, %i failures, %i unsupported features", - total - (failures + unsupported), - failures, - unsupported, - ) - return 1 - - -if __name__ == "__main__": - sys.exit(main()) +templock = threading.Lock() diff --git a/cwltest/__main__.py b/cwltest/__main__.py new file mode 100644 index 0000000..ee36e8b --- /dev/null +++ b/cwltest/__main__.py @@ -0,0 +1,5 @@ +"""Default entrypoint for the cwltest module.""" + +from . import main + +main.main() diff --git a/cwltest/argparser.py b/cwltest/argparser.py new file mode 100644 index 0000000..b567622 --- /dev/null +++ b/cwltest/argparser.py @@ -0,0 +1,114 @@ +"""Command line argument parsing for cwltest.""" +import argparse +import sys + +import pkg_resources + +from cwltest import DEFAULT_TIMEOUT + + +def arg_parser(): # type: () -> argparse.ArgumentParser + """Generate a command Line argument parser for cwltest.""" + parser = argparse.ArgumentParser( + description="Common Workflow Language testing framework" + ) + parser.add_argument( + "--test", type=str, help="YAML file describing test cases", required=True + ) + parser.add_argument( + "--basedir", type=str, help="Basedir to use for tests", default="." + ) + parser.add_argument("-l", action="https://github.com/store_true", help="List tests then exit") + parser.add_argument( + "-n", type=str, default=None, help="Run specific tests, format is 1,3-6,9" + ) + parser.add_argument( + "-s", + type=str, + default=None, + help="Run specific tests using their short names separated by comma", + ) + parser.add_argument( + "-N", + type=str, + default=None, + help="Exclude specific tests by number, format is 1,3-6,9", + ) + parser.add_argument( + "-S", + type=str, + default=None, + help="Exclude specific tests by short names separated by comma", + ) + parser.add_argument( + "--tool", + type=str, + default="cwl-runner", + help="CWL runner executable to use (default 'cwl-runner'", + ) + parser.add_argument( + "--only-tools", action="https://github.com/store_true", help="Only test CommandLineTools" + ) + parser.add_argument("--tags", type=str, default=None, help="Tags to be tested") + parser.add_argument( + "--exclude-tags", type=str, default=None, help="Tags not to be tested" + ) + parser.add_argument("--show-tags", action="https://github.com/store_true", help="Show all Tags.") + parser.add_argument( + "--junit-xml", type=str, default=None, help="Path to JUnit xml file" + ) + parser.add_argument( + "--junit-verbose", + action="https://github.com/store_true", + help="Store more verbose output to JUnit xml file", + ) + parser.add_argument( + "--test-arg", + type=str, + help="Additional argument " + "given in test cases and required prefix for tool runner.", + default=None, + metavar="cache==--cache-dir", + action="https://github.com/append", + dest="testargs", + ) + parser.add_argument( + "args", help="arguments to pass first to tool runner", nargs=argparse.REMAINDER + ) + parser.add_argument( + "-j", + type=int, + default=1, + help="Specifies the number of tests to run simultaneously " + "(defaults to one).", + ) + parser.add_argument( + "--verbose", action="https://github.com/store_true", help="More verbose output during test run." + ) + parser.add_argument( + "--classname", + type=str, + default="", + help="Specify classname for the Test Suite.", + ) + parser.add_argument( + "--timeout", + type=int, + default=DEFAULT_TIMEOUT, + help="Time of execution in seconds after which the test will be " + "skipped. Defaults to {} seconds ({} minutes).".format( + DEFAULT_TIMEOUT, DEFAULT_TIMEOUT / 60 + ), + ) + parser.add_argument( + "--badgedir", type=str, help="Directory that stores JSON files for badges." + ) + + pkg = pkg_resources.require("cwltest") + if pkg: + ver = f"{sys.argv[0]} {pkg[0].version}" + else: + ver = "{} {}".format(sys.argv[0], "unknown version") + parser.add_argument("--version", action="https://github.com/version", version=ver) + + return parser diff --git a/cwltest/main.py b/cwltest/main.py new file mode 100644 index 0000000..3652764 --- /dev/null +++ b/cwltest/main.py @@ -0,0 +1,458 @@ +#!/usr/bin/env python3 +"""Entry point for cwltest.""" + +import argparse +import json +import os +import shlex +import shutil +import subprocess # nosec +import sys +import time +from collections import defaultdict +from concurrent.futures import ThreadPoolExecutor +from typing import Any, Dict, List, Optional, Set, Union + +import junit_xml +import pkg_resources +import ruamel.yaml.scanner +import schema_salad.avro +import schema_salad.ref_resolver +import schema_salad.schema +from rdflib import Graph + +from cwltest import REQUIRED, UNSUPPORTED_FEATURE, logger, utils +from cwltest.argparser import arg_parser +from cwltest.utils import TestResult + + +def _run_test( + args, # type: argparse.Namespace + test, # type: Dict[str, str] + test_number, # type: int + total_tests, # type: int + timeout, # type: int + junit_verbose=False, # type: bool + verbose=False, # type: bool +): # type: (...) -> TestResult + out = {} # type: Dict[str,Any] + outdir = outstr = outerr = "" + test_command = [] # type: List[str] + duration = 0.0 + process = None # type: Optional[subprocess.Popen[str]] + prefix = "" + suffix = "" + if sys.stderr.isatty(): + prefix = "\r" + else: + suffix = "\n" + try: + cwd = os.getcwd() + test_command = utils.prepare_test_command( + args.tool, args.args, args.testargs, test, cwd, junit_verbose + ) + + if test.get("short_name"): + sys.stderr.write( + "%sTest [%i/%i] %s: %s%s\n" + % ( + prefix, + test_number, + total_tests, + test.get("short_name"), + test.get("doc", "").replace("\n", " ").strip(), + suffix, + ) + ) + else: + sys.stderr.write( + "%sTest [%i/%i] %s%s\n" + % ( + prefix, + test_number, + total_tests, + test.get("doc", "").replace("\n", " ").strip(), + suffix, + ) + ) + if verbose: + sys.stderr.write(f"Running: {' '.join(test_command)}\n") + sys.stderr.flush() + + start_time = time.time() + stderr = subprocess.PIPE if not args.verbose else None + process = subprocess.Popen( # nosec + test_command, + stdout=subprocess.PIPE, + stderr=stderr, + universal_newlines=True, + cwd=cwd, + ) + outstr, outerr = process.communicate(timeout=timeout) + return_code = process.poll() + duration = time.time() - start_time + if return_code: + raise subprocess.CalledProcessError(return_code, " ".join(test_command)) + + out = json.loads(outstr) + except ValueError as err: + logger.error(str(err)) + logger.error(outstr) + logger.error(outerr) + except subprocess.CalledProcessError as err: + if err.returncode == UNSUPPORTED_FEATURE and REQUIRED not in test.get( + "tags", ["required"] + ): + return utils.TestResult( + UNSUPPORTED_FEATURE, outstr, outerr, duration, args.classname + ) + if test.get("should_fail", False): + return utils.TestResult(0, outstr, outerr, duration, args.classname) + logger.error( + """Test %i failed: %s""", + test_number, + " ".join([shlex.quote(tc) for tc in test_command]), + ) + logger.error(test.get("doc", "").replace("\n", " ").strip()) + if err.returncode == UNSUPPORTED_FEATURE: + logger.error("Does not support required feature") + else: + logger.error("Returned non-zero") + logger.error(outerr) + return utils.TestResult(1, outstr, outerr, duration, args.classname, str(err)) + except (ruamel.yaml.scanner.ScannerError, TypeError) as err: + logger.error( + """Test %i failed: %s""", + test_number, + " ".join([shlex.quote(tc) for tc in test_command]), + ) + logger.error(outstr) + logger.error("Parse error %s", str(err)) + logger.error(outerr) + except KeyboardInterrupt: + logger.error( + """Test %i interrupted: %s""", + test_number, + " ".join([shlex.quote(tc) for tc in test_command]), + ) + raise + except subprocess.TimeoutExpired: + logger.error( + """Test %i timed out: %s""", + test_number, + " ".join([shlex.quote(tc) for tc in test_command]), + ) + logger.error(test.get("doc", "").replace("\n", " ").strip()) + # Kill and re-communicate to get the logs and reap the child, as + # instructed in the subprocess docs. + if process: + process.kill() + outstr, outerr = process.communicate() + return utils.TestResult( + 2, outstr, outerr, timeout, args.classname, "Test timed out" + ) + finally: + if process is not None and process.returncode is None: + logger.error("""Terminating lingering process""") + process.terminate() + for _ in range(0, 3): + time.sleep(1) + if process.poll() is not None: + break + if process.returncode is None: + process.kill() + + fail_message = "" + + if test.get("should_fail", False): + logger.warning( + """Test %i failed: %s""", + test_number, + " ".join([shlex.quote(tc) for tc in test_command]), + ) + logger.warning(test.get("doc", "").replace("\n", " ").strip()) + logger.warning("Returned zero but it should be non-zero") + return utils.TestResult(1, outstr, outerr, duration, args.classname) + + try: + utils.compare(test.get("output"), out) + except utils.CompareFail as ex: + logger.warning( + """Test %i failed: %s""", + test_number, + " ".join([shlex.quote(tc) for tc in test_command]), + ) + logger.warning(test.get("doc", "").replace("\n", " ").strip()) + logger.warning("Compare failure %s", ex) + fail_message = str(ex) + + if outdir: + shutil.rmtree(outdir, True) + + return utils.TestResult( + (1 if fail_message else 0), + outstr, + outerr, + duration, + args.classname, + fail_message, + ) + + +def _expand_number_range(nr: str) -> List[int]: + result: List[int] = [] + for s in nr.split(","): + sp = s.split("-") + if len(sp) == 2: + result.extend(range(int(sp[0]) - 1, int(sp[1]))) + else: + result.append(int(s) - 1) + return result + + +def main() -> int: + """Run the main logic loop.""" + args = arg_parser().parse_args(sys.argv[1:]) + if "--" in args.args: + args.args.remove("--") + + # Remove test arguments with wrong syntax + if args.testargs is not None: + args.testargs = [ + testarg for testarg in args.testargs if testarg.count("==") == 1 + ] + + if not args.test: + arg_parser().print_help() + return 1 + + schema_resource = pkg_resources.resource_stream(__name__, "cwltest-schema.yml") + cache = { + "https://w3id.org/cwl/cwltest/cwltest-schema.yml": schema_resource.read().decode( + "utf-8" + ) + } # type: Optional[Dict[str, Union[str, Graph, bool]]] + (document_loader, avsc_names, _, _,) = schema_salad.schema.load_schema( + "https://w3id.org/cwl/cwltest/cwltest-schema.yml", cache=cache + ) + + if not isinstance(avsc_names, schema_salad.avro.schema.Names): + print(avsc_names) + return 1 + + tests, metadata = schema_salad.schema.load_and_validate( + document_loader, avsc_names, args.test, True + ) + + failures = 0 + unsupported = 0 + passed = 0 + suite_name, _ = os.path.splitext(os.path.basename(args.test)) + report = junit_xml.TestSuite(suite_name, []) + + # the number of total tests, failed tests, unsupported tests and passed tests for each tag + ntotal = defaultdict(int) # type: Dict[str, int] + nfailures = defaultdict(int) # type: Dict[str, int] + nunsupported = defaultdict(int) # type: Dict[str, int] + npassed = defaultdict(int) # type: Dict[str, int] + + if args.only_tools: + alltests = tests + tests = [] + for t in alltests: + loader = schema_salad.ref_resolver.Loader({"id": "@id"}) + cwl = loader.resolve_ref(t["tool"])[0] + if isinstance(cwl, dict): + if cwl["class"] == "CommandLineTool": + tests.append(t) + else: + raise Exception("Unexpected code path.") + + if args.tags: + alltests = tests + tests = [] + tags = args.tags.split(",") + for t in alltests: + ts = t.get("tags", []) + if any(tag in ts for tag in tags): + tests.append(t) + + if args.exclude_tags: + ex_tests = [] + tags = args.exclude_tags.split(",") + for t in tests: + ts = t.get("tags", []) + if all(tag not in ts for tag in tags): + ex_tests.append(t) + tests = ex_tests + + for t in tests: + if t.get("label"): + logger.warning("The `label` field is deprecated. Use `id` field instead.") + t["short_name"] = t["label"] + elif t.get("id"): + if isinstance(t.get("id"), str): + t["short_name"] = utils.shortname(t["id"]) + else: + logger.warning( + "The `id` field with integer is deprecated. Use string identifier instead." + ) + else: + logger.warning("The `id` field is missing.") + + if args.show_tags: + alltags = set() # type: Set[str] + for t in tests: + ts = t.get("tags", []) + alltags |= set(ts) + for tag in alltags: + print(tag) + return 0 + + if args.l: + for i, t in enumerate(tests): + if t.get("short_name"): + print( + "[%i] %s: %s" + % ( + i + 1, + t["short_name"], + t.get("doc", "").replace("\n", " ").strip(), + ) + ) + else: + print("[%i] %s" % (i + 1, t.get("doc", "").replace("\n", " ").strip())) + + return 0 + + if args.n is not None or args.s is not None: + ntest = [] + if args.n is not None: + ntest = _expand_number_range(args.n) + if args.s is not None: + for s in args.s.split(","): + test_number = utils.get_test_number_by_key(tests, "short_name", s) + if test_number: + ntest.append(test_number) + else: + logger.error('Test with short name "%s" not found ', s) + return 1 + else: + ntest = list(range(0, len(tests))) + + exclude_n = [] + if args.N is not None: + exclude_n = _expand_number_range(args.N) + if args.S is not None: + for s in args.S.split(","): + test_number = utils.get_test_number_by_key(tests, "short_name", s) + if test_number: + exclude_n.append(test_number) + else: + logger.error('Test with short name "%s" not found ', s) + return 1 + + ntest = list(filter(lambda x: x not in exclude_n, ntest)) + + total = 0 + with ThreadPoolExecutor(max_workers=args.j) as executor: + jobs = [ + executor.submit( + _run_test, + args, + tests[i], + i + 1, + len(tests), + args.timeout, + args.junit_verbose, + args.verbose, + ) + for i in ntest + ] + try: + for i, job in zip(ntest, jobs): + test_result = job.result() + test_case = test_result.create_test_case(tests[i]) + test_case.url = f"cwltest:{suite_name}#{i + 1}" + total += 1 + tags = tests[i].get("tags", []) + for t in tags: + ntotal[t] += 1 + + return_code = test_result.return_code + category = test_case.category + if return_code == 0: + passed += 1 + for t in tags: + npassed[t] += 1 + elif return_code != UNSUPPORTED_FEATURE: + failures += 1 + for t in tags: + nfailures[t] += 1 + test_case.add_failure_info(output=test_result.message) + elif return_code == UNSUPPORTED_FEATURE and category == REQUIRED: + failures += 1 + for t in tags: + nfailures[t] += 1 + test_case.add_failure_info(output=test_result.message) + elif category != REQUIRED and return_code == UNSUPPORTED_FEATURE: + unsupported += 1 + for t in tags: + nunsupported[t] += 1 + test_case.add_skipped_info("Unsupported") + else: + raise Exception( + "This is impossible, return_code: {}, category: " + "{}".format(return_code, category) + ) + report.test_cases.append(test_case) + except KeyboardInterrupt: + for job in jobs: + job.cancel() + logger.error("Tests interrupted") + + if args.junit_xml: + with open(args.junit_xml, "w") as xml: + junit_xml.to_xml_report_file(xml, [report]) + + if args.badgedir: + os.mkdir(args.badgedir) + for t, v in ntotal.items(): + percent = int((npassed[t] / float(v)) * 100) + if npassed[t] == v: + color = "green" + elif t == "required": + color = "red" + else: + color = "yellow" + + with open(f"{args.badgedir}/{t}.json", "w") as out: + out.write( + json.dumps( + { + "subject": f"{t}", + "status": f"{percent}%", + "color": color, + } + ) + ) + + if failures == 0 and unsupported == 0: + logger.info("All tests passed") + return 0 + if failures == 0 and unsupported > 0: + logger.warning( + "%i tests passed, %i unsupported features", total - unsupported, unsupported + ) + return 0 + logger.warning( + "%i tests passed, %i failures, %i unsupported features", + total - (failures + unsupported), + failures, + unsupported, + ) + return 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/cwltest/tests/test_argparse.py b/cwltest/tests/test_argparse.py index 729cd5c..4234ba6 100644 --- a/cwltest/tests/test_argparse.py +++ b/cwltest/tests/test_argparse.py @@ -1,4 +1,4 @@ -from cwltest import arg_parser +from cwltest.argparser import arg_parser def test_arg(): diff --git a/cwltest/tests/test_categories.py b/cwltest/tests/test_categories.py index 9da4e30..38461fc 100644 --- a/cwltest/tests/test_categories.py +++ b/cwltest/tests/test_categories.py @@ -16,8 +16,8 @@ def test_unsupported_with_required_tests(): get_data("tests/test-data/required-unsupported.yml") ), ] + cwd = os.getcwd() try: - cwd = os.getcwd() os.chdir(get_data("tests/test-data/")) error_code, stdout, stderr = run_with_mock_cwl_runner(args) finally: diff --git a/cwltest/tests/test_compare.py b/cwltest/tests/test_compare.py index 15003ed..826a253 100644 --- a/cwltest/tests/test_compare.py +++ b/cwltest/tests/test_compare.py @@ -1,6 +1,5 @@ from .util import get_data -from cwltest import CompareFail -from cwltest.utils import compare_file, compare +from cwltest.utils import CompareFail, compare_file, compare import pytest diff --git a/cwltest/tests/test_exclude_tags.py b/cwltest/tests/test_exclude_tags.py index db01989..26283bd 100644 --- a/cwltest/tests/test_exclude_tags.py +++ b/cwltest/tests/test_exclude_tags.py @@ -1,9 +1,6 @@ -import os from os import linesep as n -from pathlib import Path -from .util import run_with_mock_cwl_runner, get_data -import defusedxml.ElementTree as ET +from .util import get_data, run_with_mock_cwl_runner def test_list_only_exclude(): diff --git a/cwltest/tests/test_integer_id.py b/cwltest/tests/test_integer_id.py index 7993111..7b0363f 100644 --- a/cwltest/tests/test_integer_id.py +++ b/cwltest/tests/test_integer_id.py @@ -1,9 +1,4 @@ -import os -from os import linesep as n -from pathlib import Path - -from .util import run_with_mock_cwl_runner, get_data -import defusedxml.ElementTree as ET +from .util import get_data, run_with_mock_cwl_runner def test_warning_with_integer_id(): diff --git a/cwltest/tests/test_multi_lined_doc.py b/cwltest/tests/test_multi_lined_doc.py index 9b6f4b3..a5d8ea9 100644 --- a/cwltest/tests/test_multi_lined_doc.py +++ b/cwltest/tests/test_multi_lined_doc.py @@ -1,9 +1,6 @@ -import os from os import linesep as n -from pathlib import Path -from .util import run_with_mock_cwl_runner, get_data -import defusedxml.ElementTree as ET +from .util import get_data, run_with_mock_cwl_runner def test_run(): diff --git a/cwltest/tests/test_prepare.py b/cwltest/tests/test_prepare.py index 3c2ff6f..f93a19b 100644 --- a/cwltest/tests/test_prepare.py +++ b/cwltest/tests/test_prepare.py @@ -1,11 +1,12 @@ """Test prepare_test_command()""" import os -from cwltest import prepare_test_command + +from cwltest import utils def test_unix_relative_path(): """Confirm unix style to windows style path corrections.""" - command = prepare_test_command( + command = utils.prepare_test_command( tool="cwl-runner", args=[], testargs=None, diff --git a/cwltest/tests/test_short_names.py b/cwltest/tests/test_short_names.py index 84a594c..d16c762 100644 --- a/cwltest/tests/test_short_names.py +++ b/cwltest/tests/test_short_names.py @@ -1,10 +1,10 @@ -import os from os import linesep as n from pathlib import Path -from .util import run_with_mock_cwl_runner, get_data import defusedxml.ElementTree as ET +from .util import get_data, run_with_mock_cwl_runner + def test_stderr_output(): args = ["--test", get_data("tests/test-data/short-names.yml")] diff --git a/cwltest/tests/test_string_id.py b/cwltest/tests/test_string_id.py index 77180ae..09e58c3 100644 --- a/cwltest/tests/test_string_id.py +++ b/cwltest/tests/test_string_id.py @@ -1,9 +1,6 @@ -import os from os import linesep as n -from pathlib import Path -from .util import run_with_mock_cwl_runner, get_data -import defusedxml.ElementTree as ET +from .util import get_data, run_with_mock_cwl_runner def test_list(): diff --git a/cwltest/tests/test_timeout.py b/cwltest/tests/test_timeout.py index 431e665..bd27c86 100644 --- a/cwltest/tests/test_timeout.py +++ b/cwltest/tests/test_timeout.py @@ -1,14 +1,10 @@ -import re import os -from os import linesep as n -from os import sep as p -from pathlib import Path import defusedxml.ElementTree as ET - -from .util import run_with_mock_cwl_runner, get_data import schema_salad.ref_resolver +from .util import get_data, run_with_mock_cwl_runner + def test_timeout_stderr_stdout(tmp_path): junit_xml_report = tmp_path / "junit-report.xml" @@ -21,8 +17,8 @@ def test_timeout_stderr_stdout(tmp_path): "--junit-xml", str(junit_xml_report), ] + cwd = os.getcwd() try: - cwd = os.getcwd() os.chdir(get_data("tests/test-data/")) error_code, stdout, stderr = run_with_mock_cwl_runner(args) finally: diff --git a/cwltest/utils.py b/cwltest/utils.py index 50e1cb5..632e513 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -1,13 +1,17 @@ import json +import os +import re +import sys +import tempfile from typing import Any, Dict, List, Optional, Set, Text import junit_xml +import schema_salad.ref_resolver -REQUIRED = "required" +from cwltest import REQUIRED, templock class TestResult: - """Encapsulate relevant test result data.""" def __init__( @@ -20,6 +24,7 @@ def __init__( message="", ): # type: (int, Text, Text, float, Text, str) -> None + """Initialize a TestResult object.""" self.return_code = return_code self.standard_output = standard_output self.error_output = error_output @@ -209,3 +214,63 @@ def get_test_number_by_key(tests, key, value): if key in test and test[key] == value: return i return None + + +def prepare_test_command( + tool, # type: str + args, # type: List[str] + testargs, # type: Optional[List[str]] + test, # type: Dict[str, Any] + cwd, # type: str + verbose=False, # type: bool +): # type: (...) -> List[str] + """Turn the test into a command line.""" + test_command = [tool] + test_command.extend(args) + + # Add additional arguments given in test case + if testargs is not None: + for testarg in testargs: + (test_case_name, prefix) = testarg.split("==") + if test_case_name in test: + test_command.extend([prefix, test[test_case_name]]) + + # Add prefixes if running on MacOSX so that boot2docker writes to /Users + with templock: + if "darwin" in sys.platform and tool.endswith("cwltool"): + outdir = tempfile.mkdtemp(prefix=os.path.abspath(os.path.curdir)) + test_command.extend( + [ + f"--tmp-outdir-prefix={outdir}", + f"--tmpdir-prefix={outdir}", + ] + ) + else: + outdir = tempfile.mkdtemp() + test_command.extend([f"--outdir={outdir}"]) + if not verbose: + test_command.extend(["--quiet"]) + + cwd = schema_salad.ref_resolver.file_uri(cwd) + toolpath = test["tool"] + if toolpath.startswith(cwd): + toolpath = toolpath[len(cwd) + 1 :] + test_command.extend([os.path.normcase(toolpath)]) + + jobpath = test.get("job") + if jobpath: + if jobpath.startswith(cwd): + jobpath = jobpath[len(cwd) + 1 :] + test_command.append(os.path.normcase(jobpath)) + return test_command + + +def shortname( + name, # type: str +): # type: (...) -> str + """ + Return the short name of a given name. + + It is a workaround of https://github.com/common-workflow-language/schema_salad/issues/511. + """ + return [n for n in re.split("[/#]", name) if len(n)][-1] diff --git a/setup.py b/setup.py index 6466981..cd9349d 100644 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ tests_require=["pytest<8"], entry_points={ "console_scripts": [ - "cwltest=cwltest:main", + "cwltest=cwltest.main:main", "mock-cwl-runner=cwltest.tests.mock_cwl_runner:main", ] }, diff --git a/tox.ini b/tox.ini index 37b83b3..bd79838 100644 --- a/tox.ini +++ b/tox.ini @@ -54,7 +54,7 @@ commands = py{37,38,39,310,311}-mypy: make mypy py37-mypy: make mypy_3.6 -whitelist_externals = +allowlist_externals = py{36,37,38,39,310,311}-lint: flake8 py{36,37,38,39,310,311}-lint: black py{36,37,38,39,310,311}-{mypy,shellcheck,lint,unit}: make @@ -65,7 +65,7 @@ skip_install = [testenv:py310-pydocstyle] -whitelist_externals = make +allowlist_externals = make commands = make diff_pydocstyle_report deps = pydocstyle From 88bfd6e981e884e2647953956db67ce674a572fd Mon Sep 17 00:00:00 2001 From: Iacopo Colonnelli Date: Wed, 4 Jan 2023 14:30:46 +0100 Subject: [PATCH 053/165] Refactoring test suite (#156) * Refactoring test suite This commit reorganizes the test suite in three ways: - It moves the tests folder to the top of the hierarchy - It extends format, mypy, and pydocstyle checks to test folder - It better types the test functions to make them compatible with MyPy checks * cwltest/tests -> tests * Adjusted mypy for defusedxml --- .coveragerc | 5 ++-- MANIFEST.in | 6 ++--- Makefile | 4 ++-- mypy-stubs/defusedxml/ElementTree.pyi | 6 +++++ .../defusedxml}/__init__.py | 0 setup.py | 6 +++-- tests/__init__.py | 1 + {cwltest/tests => tests}/test-data/cores.txt | 0 .../test-data/exclude-tags.yml | 0 .../tests => tests}/test-data/integer-id.yml | 0 .../test-data}/mock_cwl_runner.py | 3 +++ .../test-data/multi-lined-doc.yml | 0 .../test-data/optional-error.yml | 0 .../test-data/optional-unsupported.yml | 0 .../test-data/required-unsupported.yml | 0 .../tests => tests}/test-data/return-0.cwl | 0 .../tests => tests}/test-data/return-1.cwl | 0 .../test-data/return-unsupported.cwl | 0 .../tests => tests}/test-data/short-names.yml | 0 .../tests => tests}/test-data/string-id.yml | 0 .../tests => tests}/test-data/timeout.cwl | 0 .../tests => tests}/test-data/timeout.yml | 0 .../test-data/v1.0/cat-job.json | 0 .../test-data/v1.0/cat1-job.json | 0 .../test-data/v1.0/cat2-job.json | 0 .../tests => tests}/test-data/v1.0/empty.json | 0 .../with-and-without-short-names.yml | 0 {cwltest/tests => tests}/test_argparse.py | 2 +- {cwltest/tests => tests}/test_categories.py | 23 ++++++++++++------- {cwltest/tests => tests}/test_compare.py | 6 ++--- {cwltest/tests => tests}/test_exclude_tags.py | 4 ++-- {cwltest/tests => tests}/test_integer_id.py | 2 +- .../tests => tests}/test_multi_lined_doc.py | 4 ++-- {cwltest/tests => tests}/test_prepare.py | 2 +- {cwltest/tests => tests}/test_short_names.py | 14 +++++++---- {cwltest/tests => tests}/test_string_id.py | 2 +- {cwltest/tests => tests}/test_timeout.py | 23 +++++++++++++++---- {cwltest/tests => tests}/util.py | 13 +++++++---- tox.ini | 6 ++--- 39 files changed, 85 insertions(+), 47 deletions(-) create mode 100644 mypy-stubs/defusedxml/ElementTree.pyi rename {cwltest/tests => mypy-stubs/defusedxml}/__init__.py (100%) create mode 100644 tests/__init__.py rename {cwltest/tests => tests}/test-data/cores.txt (100%) rename {cwltest/tests => tests}/test-data/exclude-tags.yml (100%) rename {cwltest/tests => tests}/test-data/integer-id.yml (100%) rename {cwltest/tests => tests/test-data}/mock_cwl_runner.py (91%) mode change 100644 => 100755 rename {cwltest/tests => tests}/test-data/multi-lined-doc.yml (100%) rename {cwltest/tests => tests}/test-data/optional-error.yml (100%) rename {cwltest/tests => tests}/test-data/optional-unsupported.yml (100%) rename {cwltest/tests => tests}/test-data/required-unsupported.yml (100%) rename {cwltest/tests => tests}/test-data/return-0.cwl (100%) rename {cwltest/tests => tests}/test-data/return-1.cwl (100%) rename {cwltest/tests => tests}/test-data/return-unsupported.cwl (100%) rename {cwltest/tests => tests}/test-data/short-names.yml (100%) rename {cwltest/tests => tests}/test-data/string-id.yml (100%) rename {cwltest/tests => tests}/test-data/timeout.cwl (100%) rename {cwltest/tests => tests}/test-data/timeout.yml (100%) rename {cwltest/tests => tests}/test-data/v1.0/cat-job.json (100%) rename {cwltest/tests => tests}/test-data/v1.0/cat1-job.json (100%) rename {cwltest/tests => tests}/test-data/v1.0/cat2-job.json (100%) rename {cwltest/tests => tests}/test-data/v1.0/empty.json (100%) rename {cwltest/tests => tests}/test-data/with-and-without-short-names.yml (100%) rename {cwltest/tests => tests}/test_argparse.py (93%) rename {cwltest/tests => tests}/test_categories.py (77%) rename {cwltest/tests => tests}/test_compare.py (93%) rename {cwltest/tests => tests}/test_exclude_tags.py (90%) rename {cwltest/tests => tests}/test_integer_id.py (88%) rename {cwltest/tests => tests}/test_multi_lined_doc.py (93%) rename {cwltest/tests => tests}/test_prepare.py (95%) rename {cwltest/tests => tests}/test_short_names.py (79%) rename {cwltest/tests => tests}/test_string_id.py (92%) rename {cwltest/tests => tests}/test_timeout.py (53%) rename {cwltest/tests => tests}/util.py (65%) diff --git a/.coveragerc b/.coveragerc index 4a89de0..020763e 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,7 +1,7 @@ [run] branch = True source = cwltest -omit = cwltest/tests/* +omit = tests/* [report] exclude_lines = @@ -10,5 +10,4 @@ exclude_lines = raise NotImplementedError if __name__ == .__main__.: ignore_errors = True -omit = - cwltest/tests/* +omit = tests/* diff --git a/MANIFEST.in b/MANIFEST.in index f902163..1eab7bf 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,8 +1,8 @@ include Makefile gittaggers.py test-requirements.txt mypy-requirements.txt requirements.txt include cwltest/cwltest-schema.yml -include cwltest/tests/* -include cwltest/tests/test-data/* -include cwltest/tests/test-data/v1.0/* +include tests/* +include tests/test-data/* +include tests/test-data/v1.0/* recursive-include mypy-stubs *.py? global-exclude *~ global-exclude *.pyc diff --git a/Makefile b/Makefile index 1e84799..c65f07b 100644 --- a/Makefile +++ b/Makefile @@ -102,10 +102,10 @@ codespell: ## format : check/fix all code indentation and formatting (runs black) format: - black setup.py cwltest setup.py mypy-stubs + black setup.py setup.py cwltest tests mypy-stubs format-check: - black --diff --check setup.py cwltest mypy-stubs + black --diff --check setup.py cwltest tests mypy-stubs ## pylint : run static code analysis on Python code pylint: $(PYSOURCES) diff --git a/mypy-stubs/defusedxml/ElementTree.pyi b/mypy-stubs/defusedxml/ElementTree.pyi new file mode 100644 index 0000000..e6f2465 --- /dev/null +++ b/mypy-stubs/defusedxml/ElementTree.pyi @@ -0,0 +1,6 @@ +import xml.etree.ElementTree +from pathlib import Path + +def parse( + source: Path = ..., parser: xml.etree.ElementTree.XMLParser = ... +) -> xml.etree.ElementTree.ElementTree: ... diff --git a/cwltest/tests/__init__.py b/mypy-stubs/defusedxml/__init__.py similarity index 100% rename from cwltest/tests/__init__.py rename to mypy-stubs/defusedxml/__init__.py diff --git a/setup.py b/setup.py index cd9349d..e2b1528 100644 --- a/setup.py +++ b/setup.py @@ -5,6 +5,8 @@ import setuptools.command.egg_info as egg_info_cmd from setuptools import setup +import cwltest + SETUP_DIR = os.path.dirname(__file__) README = os.path.join(SETUP_DIR, "README.rst") @@ -38,7 +40,8 @@ python_requires=">=3.6, <4", setup_requires=[] + pytest_runner, packages=["cwltest", "cwltest.tests"], - package_data={"cwltest": ["py.typed"], "cwltest.tests": ["test-data/*"]}, + package_dir={"cwltest.tests": "tests"}, + package_data={"cwltest": ["py.typed"], "tests": ["test-data/*"]}, include_package_data=True, install_requires=install_requires, test_suite="tests", @@ -46,7 +49,6 @@ entry_points={ "console_scripts": [ "cwltest=cwltest.main:main", - "mock-cwl-runner=cwltest.tests.mock_cwl_runner:main", ] }, zip_safe=True, diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..198807d --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Tests for cwltest.""" diff --git a/cwltest/tests/test-data/cores.txt b/tests/test-data/cores.txt similarity index 100% rename from cwltest/tests/test-data/cores.txt rename to tests/test-data/cores.txt diff --git a/cwltest/tests/test-data/exclude-tags.yml b/tests/test-data/exclude-tags.yml similarity index 100% rename from cwltest/tests/test-data/exclude-tags.yml rename to tests/test-data/exclude-tags.yml diff --git a/cwltest/tests/test-data/integer-id.yml b/tests/test-data/integer-id.yml similarity index 100% rename from cwltest/tests/test-data/integer-id.yml rename to tests/test-data/integer-id.yml diff --git a/cwltest/tests/mock_cwl_runner.py b/tests/test-data/mock_cwl_runner.py old mode 100644 new mode 100755 similarity index 91% rename from cwltest/tests/mock_cwl_runner.py rename to tests/test-data/mock_cwl_runner.py index 478e504..d807203 --- a/cwltest/tests/mock_cwl_runner.py +++ b/tests/test-data/mock_cwl_runner.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python3 +"""Mock implementation of the cwlref-runner command line.""" + import argparse import sys from time import sleep diff --git a/cwltest/tests/test-data/multi-lined-doc.yml b/tests/test-data/multi-lined-doc.yml similarity index 100% rename from cwltest/tests/test-data/multi-lined-doc.yml rename to tests/test-data/multi-lined-doc.yml diff --git a/cwltest/tests/test-data/optional-error.yml b/tests/test-data/optional-error.yml similarity index 100% rename from cwltest/tests/test-data/optional-error.yml rename to tests/test-data/optional-error.yml diff --git a/cwltest/tests/test-data/optional-unsupported.yml b/tests/test-data/optional-unsupported.yml similarity index 100% rename from cwltest/tests/test-data/optional-unsupported.yml rename to tests/test-data/optional-unsupported.yml diff --git a/cwltest/tests/test-data/required-unsupported.yml b/tests/test-data/required-unsupported.yml similarity index 100% rename from cwltest/tests/test-data/required-unsupported.yml rename to tests/test-data/required-unsupported.yml diff --git a/cwltest/tests/test-data/return-0.cwl b/tests/test-data/return-0.cwl similarity index 100% rename from cwltest/tests/test-data/return-0.cwl rename to tests/test-data/return-0.cwl diff --git a/cwltest/tests/test-data/return-1.cwl b/tests/test-data/return-1.cwl similarity index 100% rename from cwltest/tests/test-data/return-1.cwl rename to tests/test-data/return-1.cwl diff --git a/cwltest/tests/test-data/return-unsupported.cwl b/tests/test-data/return-unsupported.cwl similarity index 100% rename from cwltest/tests/test-data/return-unsupported.cwl rename to tests/test-data/return-unsupported.cwl diff --git a/cwltest/tests/test-data/short-names.yml b/tests/test-data/short-names.yml similarity index 100% rename from cwltest/tests/test-data/short-names.yml rename to tests/test-data/short-names.yml diff --git a/cwltest/tests/test-data/string-id.yml b/tests/test-data/string-id.yml similarity index 100% rename from cwltest/tests/test-data/string-id.yml rename to tests/test-data/string-id.yml diff --git a/cwltest/tests/test-data/timeout.cwl b/tests/test-data/timeout.cwl similarity index 100% rename from cwltest/tests/test-data/timeout.cwl rename to tests/test-data/timeout.cwl diff --git a/cwltest/tests/test-data/timeout.yml b/tests/test-data/timeout.yml similarity index 100% rename from cwltest/tests/test-data/timeout.yml rename to tests/test-data/timeout.yml diff --git a/cwltest/tests/test-data/v1.0/cat-job.json b/tests/test-data/v1.0/cat-job.json similarity index 100% rename from cwltest/tests/test-data/v1.0/cat-job.json rename to tests/test-data/v1.0/cat-job.json diff --git a/cwltest/tests/test-data/v1.0/cat1-job.json b/tests/test-data/v1.0/cat1-job.json similarity index 100% rename from cwltest/tests/test-data/v1.0/cat1-job.json rename to tests/test-data/v1.0/cat1-job.json diff --git a/cwltest/tests/test-data/v1.0/cat2-job.json b/tests/test-data/v1.0/cat2-job.json similarity index 100% rename from cwltest/tests/test-data/v1.0/cat2-job.json rename to tests/test-data/v1.0/cat2-job.json diff --git a/cwltest/tests/test-data/v1.0/empty.json b/tests/test-data/v1.0/empty.json similarity index 100% rename from cwltest/tests/test-data/v1.0/empty.json rename to tests/test-data/v1.0/empty.json diff --git a/cwltest/tests/test-data/with-and-without-short-names.yml b/tests/test-data/with-and-without-short-names.yml similarity index 100% rename from cwltest/tests/test-data/with-and-without-short-names.yml rename to tests/test-data/with-and-without-short-names.yml diff --git a/cwltest/tests/test_argparse.py b/tests/test_argparse.py similarity index 93% rename from cwltest/tests/test_argparse.py rename to tests/test_argparse.py index 4234ba6..948ddd1 100644 --- a/cwltest/tests/test_argparse.py +++ b/tests/test_argparse.py @@ -1,7 +1,7 @@ from cwltest.argparser import arg_parser -def test_arg(): +def test_arg() -> None: """Basic test of the argparse.""" parser = arg_parser() parsed = parser.parse_args( diff --git a/cwltest/tests/test_categories.py b/tests/test_categories.py similarity index 77% rename from cwltest/tests/test_categories.py rename to tests/test_categories.py index 38461fc..28acb90 100644 --- a/cwltest/tests/test_categories.py +++ b/tests/test_categories.py @@ -3,13 +3,16 @@ from os import linesep as n from os import sep as p from pathlib import Path +from typing import cast +from xml.etree.ElementTree import Element from .util import run_with_mock_cwl_runner, get_data import defusedxml.ElementTree as ET import schema_salad.ref_resolver -def test_unsupported_with_required_tests(): +def test_unsupported_with_required_tests() -> None: + cwl_runner = get_data("tests/test-data/mock_cwl_runner.py") args = [ "--test", schema_salad.ref_resolver.file_uri( @@ -35,21 +38,23 @@ def test_unsupported_with_required_tests(): "The `id` field is missing.{n}" "Test [1/2] Required test that is unsupported (without tags){n}" "{n}" - "Test 1 failed: mock-cwl-runner --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" + "Test 1 failed: {cwl_runner} --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" "Required test that is unsupported (without tags){n}" "Does not support required feature{n}" "{n}" "Test [2/2] Required test that is unsupported (with tags){n}" "{n}" - "Test 2 failed: mock-cwl-runner --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" + "Test 2 failed: {cwl_runner} --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" "Required test that is unsupported (with tags){n}" "Does not support required feature{n}" "{n}" - "0 tests passed, 2 failures, 0 unsupported features{n}".format(n=n, p=p, q=q) + "0 tests passed, 2 failures, 0 unsupported features{n}".format( + cwl_runner=cwl_runner, n=n, p=p, q=q + ) ) == stderr -def test_unsupported_with_optional_tests(): +def test_unsupported_with_optional_tests() -> None: args = [ "--test", schema_salad.ref_resolver.file_uri( @@ -66,7 +71,7 @@ def test_unsupported_with_optional_tests(): ) == stderr -def test_error_with_optional_tests(): +def test_error_with_optional_tests() -> None: args = [ "--test", schema_salad.ref_resolver.file_uri( @@ -78,7 +83,7 @@ def test_error_with_optional_tests(): assert "1 failures" in stderr -def test_category_in_junit_xml(tmp_path: Path): +def test_category_in_junit_xml(tmp_path: Path) -> None: junit_xml_report = tmp_path / "junit-report.xml" args = [ "--test", @@ -91,5 +96,7 @@ def test_category_in_junit_xml(tmp_path: Path): run_with_mock_cwl_runner(args) tree = ET.parse(junit_xml_report) root = tree.getroot() - category = root.find("testsuite").find("testcase").attrib["class"] + category = cast( + Element, cast(Element, root.find("testsuite")).find("testcase") + ).attrib["class"] assert category == "js, init_work_dir" diff --git a/cwltest/tests/test_compare.py b/tests/test_compare.py similarity index 93% rename from cwltest/tests/test_compare.py rename to tests/test_compare.py index 826a253..aec983e 100644 --- a/cwltest/tests/test_compare.py +++ b/tests/test_compare.py @@ -4,7 +4,7 @@ import pytest -def test_compare_file(): +def test_compare_file() -> None: expected = { "location": "cores.txt", "size": 2, @@ -23,7 +23,7 @@ def test_compare_file(): compare_file(expected, actual) -def test_compare_contents_success(): +def test_compare_contents_success() -> None: expected = { "location": "cores.txt", "size": 2, @@ -42,7 +42,7 @@ def test_compare_contents_success(): compare(expected, actual) -def test_compare_contents_failure(): +def test_compare_contents_failure() -> None: expected = { "location": "cores.txt", "size": 2, diff --git a/cwltest/tests/test_exclude_tags.py b/tests/test_exclude_tags.py similarity index 90% rename from cwltest/tests/test_exclude_tags.py rename to tests/test_exclude_tags.py index 26283bd..f17ae48 100644 --- a/cwltest/tests/test_exclude_tags.py +++ b/tests/test_exclude_tags.py @@ -3,7 +3,7 @@ from .util import get_data, run_with_mock_cwl_runner -def test_list_only_exclude(): +def test_list_only_exclude() -> None: args = [ "--test", get_data("tests/test-data/exclude-tags.yml"), @@ -16,7 +16,7 @@ def test_list_only_exclude(): assert "opt-error3" not in stdout -def test_list_include_and_exclude(): +def test_list_include_and_exclude() -> None: args = [ "--test", get_data("tests/test-data/exclude-tags.yml"), diff --git a/cwltest/tests/test_integer_id.py b/tests/test_integer_id.py similarity index 88% rename from cwltest/tests/test_integer_id.py rename to tests/test_integer_id.py index 7b0363f..64343e3 100644 --- a/cwltest/tests/test_integer_id.py +++ b/tests/test_integer_id.py @@ -1,7 +1,7 @@ from .util import get_data, run_with_mock_cwl_runner -def test_warning_with_integer_id(): +def test_warning_with_integer_id() -> None: args = [ "--test", get_data("tests/test-data/integer-id.yml"), diff --git a/cwltest/tests/test_multi_lined_doc.py b/tests/test_multi_lined_doc.py similarity index 93% rename from cwltest/tests/test_multi_lined_doc.py rename to tests/test_multi_lined_doc.py index a5d8ea9..51ba2f9 100644 --- a/cwltest/tests/test_multi_lined_doc.py +++ b/tests/test_multi_lined_doc.py @@ -3,7 +3,7 @@ from .util import get_data, run_with_mock_cwl_runner -def test_run(): +def test_run() -> None: args = ["--test", get_data("tests/test-data/multi-lined-doc.yml")] error_code, stdout, stderr = run_with_mock_cwl_runner(args) assert "The `label` field is deprecated. Use `id` field instead." in stderr @@ -11,7 +11,7 @@ def test_run(): assert f"Test [2/2] Test without label{n}" in stderr -def test_list(): +def test_list() -> None: args = ["--test", get_data("tests/test-data/multi-lined-doc.yml"), "-l"] error_code, stdout, stderr = run_with_mock_cwl_runner(args) assert f"[1] opt-error: Test with label{n}" in stdout diff --git a/cwltest/tests/test_prepare.py b/tests/test_prepare.py similarity index 95% rename from cwltest/tests/test_prepare.py rename to tests/test_prepare.py index f93a19b..9c3c3c1 100644 --- a/cwltest/tests/test_prepare.py +++ b/tests/test_prepare.py @@ -4,7 +4,7 @@ from cwltest import utils -def test_unix_relative_path(): +def test_unix_relative_path() -> None: """Confirm unix style to windows style path corrections.""" command = utils.prepare_test_command( tool="cwl-runner", diff --git a/cwltest/tests/test_short_names.py b/tests/test_short_names.py similarity index 79% rename from cwltest/tests/test_short_names.py rename to tests/test_short_names.py index d16c762..da87b6c 100644 --- a/cwltest/tests/test_short_names.py +++ b/tests/test_short_names.py @@ -1,18 +1,20 @@ from os import linesep as n from pathlib import Path +from typing import cast +from xml.etree.ElementTree import Element import defusedxml.ElementTree as ET from .util import get_data, run_with_mock_cwl_runner -def test_stderr_output(): +def test_stderr_output() -> None: args = ["--test", get_data("tests/test-data/short-names.yml")] error_code, stdout, stderr = run_with_mock_cwl_runner(args) assert f"Test [1/1] opt-error: Test with a short name{n}" in stderr -def test_run_by_short_name(): +def test_run_by_short_name() -> None: short_name = "opt-error" args = [ "--test", @@ -25,7 +27,7 @@ def test_run_by_short_name(): assert "Test [1/2]" not in stderr -def test_list_tests(): +def test_list_tests() -> None: args = [ "--test", get_data("tests/test-data/with-and-without-short-names.yml"), @@ -37,7 +39,7 @@ def test_list_tests(): ) in stdout -def test_short_name_in_junit_xml(tmp_path: Path): +def test_short_name_in_junit_xml(tmp_path: Path) -> None: junit_xml_report = tmp_path / "junit-report.xml" args = [ "--test", @@ -48,5 +50,7 @@ def test_short_name_in_junit_xml(tmp_path: Path): run_with_mock_cwl_runner(args) tree = ET.parse(junit_xml_report) root = tree.getroot() - category = root.find("testsuite").find("testcase").attrib["file"] + category = cast( + Element, cast(Element, root.find("testsuite")).find("testcase") + ).attrib["file"] assert category == "opt-error" diff --git a/cwltest/tests/test_string_id.py b/tests/test_string_id.py similarity index 92% rename from cwltest/tests/test_string_id.py rename to tests/test_string_id.py index 09e58c3..8a9eb1f 100644 --- a/cwltest/tests/test_string_id.py +++ b/tests/test_string_id.py @@ -3,7 +3,7 @@ from .util import get_data, run_with_mock_cwl_runner -def test_list(): +def test_list() -> None: args = ["--test", get_data("tests/test-data/string-id.yml"), "-l"] error_code, stdout, stderr = run_with_mock_cwl_runner(args) assert f"[1] test-string-id: Test with a string label{n}" in stdout diff --git a/cwltest/tests/test_timeout.py b/tests/test_timeout.py similarity index 53% rename from cwltest/tests/test_timeout.py rename to tests/test_timeout.py index bd27c86..bc01636 100644 --- a/cwltest/tests/test_timeout.py +++ b/tests/test_timeout.py @@ -1,4 +1,7 @@ import os +from pathlib import Path +from typing import cast +from xml.etree.ElementTree import Element import defusedxml.ElementTree as ET import schema_salad.ref_resolver @@ -6,7 +9,7 @@ from .util import get_data, run_with_mock_cwl_runner -def test_timeout_stderr_stdout(tmp_path): +def test_timeout_stderr_stdout(tmp_path: Path) -> None: junit_xml_report = tmp_path / "junit-report.xml" args = [ @@ -29,10 +32,20 @@ def test_timeout_stderr_stdout(tmp_path): tree = ET.parse(junit_xml_report) try: root = tree.getroot() - timeout_text = root.find("testsuite").find("testcase").find("failure").text - timeout_stderr = root.find("testsuite").find("testcase").find("system-err").text - assert "Test timed out" in timeout_text - assert "timeout stderr" in timeout_stderr + timeout_text = cast( + Element, + cast(Element, cast(Element, root.find("testsuite")).find("testcase")).find( + "failure" + ), + ).text + timeout_stderr = cast( + Element, + cast(Element, cast(Element, root.find("testsuite")).find("testcase")).find( + "system-err" + ), + ).text + assert timeout_text is not None and "Test timed out" in timeout_text + assert timeout_stderr is not None and "timeout stderr" in timeout_stderr except AttributeError as e: print(junit_xml_report.read_text()) raise e diff --git a/cwltest/tests/util.py b/tests/util.py similarity index 65% rename from cwltest/tests/util.py rename to tests/util.py index 25879bc..145d0b2 100644 --- a/cwltest/tests/util.py +++ b/tests/util.py @@ -1,15 +1,16 @@ import os - import subprocess # nosec +from typing import List, Tuple from pkg_resources import ( Requirement, - ResolutionError, # type: ignore + ResolutionError, resource_filename, ) -def get_data(filename): +def get_data(filename: str) -> str: + """Return the absolute path starting from a file name.""" filename = os.path.normpath(filename) # normalizing path depending on OS or else it will cause problem when # joining path @@ -23,9 +24,11 @@ def get_data(filename): return filepath -def run_with_mock_cwl_runner(args): +def run_with_mock_cwl_runner(args: List[str]) -> Tuple[int, str, str]: + """Bind a mock cwlref-runner implementation to cwltest.""" + cwl_runner = get_data("tests/test-data/mock_cwl_runner.py") process = subprocess.Popen( # nosec - ["cwltest", "--tool", "mock-cwl-runner"] + args, + ["cwltest", "--tool", cwl_runner] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) diff --git a/tox.ini b/tox.ini index bd79838..5e47e6a 100644 --- a/tox.ini +++ b/tox.ini @@ -10,8 +10,7 @@ envlist = skip_missing_interpreters = True [pytest] -addopts = --pyargs cwltest -testpaths = cwltest/tests +testpaths = tests [gh-actions] python = @@ -34,6 +33,7 @@ description = passenv = CI GITHUB_* + deps = py{36,37,38,39,310,311}-{unit,mypy}: -rrequirements.txt py{36,37,38,39,310,311}-{unit,mypy}: -rtest-requirements.txt @@ -48,7 +48,7 @@ setenv = commands = py{36,37,38,39,310,311}-unit: python -m pip install -U pip setuptools wheel py{36,37,38,39,310,311}-unit: make coverage-report coverage.xml PYTEST_EXTRA={posargs} - py{36,37,38,39,310,311}-bandit: bandit --recursive cwltest --exclude cwltest/tests/* + py{36,37,38,39,310,311}-bandit: bandit --recursive cwltest --exclude tests/* py{36,37,38,39,310,311}-lint: make flake8 py{36,37,38,39,310,311}-lint: make format-check py{37,38,39,310,311}-mypy: make mypy From b80be607cffc488f997a78d50d6c3d2d33b1c3e0 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" <1330696+mr-c@users.noreply.github.com> Date: Sat, 7 Jan 2023 14:49:18 +0100 Subject: [PATCH 054/165] build docs (#157) --- .readthedocs.yml | 24 +++++++++ Makefile | 33 +++++-------- dev-requirements.txt | 14 ++++++ docs/Makefile | 20 ++++++++ docs/_static/favicon.ico | Bin 0 -> 15086 bytes docs/conf.py | 102 +++++++++++++++++++++++++++++++++++++++ docs/index.rst | 17 +++++++ docs/requirements.txt | 6 +++ release-test.sh | 6 +-- 9 files changed, 198 insertions(+), 24 deletions(-) create mode 100644 .readthedocs.yml create mode 100644 dev-requirements.txt create mode 100644 docs/Makefile create mode 100644 docs/_static/favicon.ico create mode 100644 docs/conf.py create mode 100644 docs/index.rst create mode 100644 docs/requirements.txt diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000..5a74019 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,24 @@ +# .readthedocs.yml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/conf.py + +# Optionally build your docs in additional formats such as PDF and ePub +formats: all + +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +python: + install: + - requirements: docs/requirements.txt + - method: pip + path: . diff --git a/Makefile b/Makefile index c65f07b..9ff55a8 100644 --- a/Makefile +++ b/Makefile @@ -26,15 +26,13 @@ PACKAGE=cwltest # `SHELL=bash` doesn't work for some, so don't use BASH-isms like # `[[` conditional expressions. PYSOURCES=$(wildcard ${MODULE}/**.py tests/*.py) setup.py -DEVPKGS=diff_cover black pylint pep257 pydocstyle flake8 tox tox-pyenv \ - isort wheel autoflake flake8-bugbear pyupgrade bandit \ - -rtest-requirements.txt -rmypy-requirements.txt +DEVPKGS=-rdev-requirements.txt -rtest-requirements.txt -rmypy-requirements.txt DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage pydocstyle sloccount \ python-flake8 python-mock shellcheck VERSION=2.2.$(shell TZ=UTC git log --first-parent --max-count=1 \ --format=format:%cd --date=format-local:%Y%m%d%H%M%S) -## all : default task +## all : default task (install in dev mode) all: dev ## help : print this help message and exit @@ -61,13 +59,18 @@ install: FORCE ## dev : install the cwltest package in dev mode dev: install-dep + pip install -U pip setuptools wheel pip install -e . ## dist : create a module package for distribution dist: dist/${MODULE}-$(VERSION).tar.gz dist/${MODULE}-$(VERSION).tar.gz: $(SOURCES) - python setup.py sdist bdist_wheel + python -m build + +## docs : make the docs +docs: FORCE + cd docs && $(MAKE) html ## clean : clean up all temporary / machine-generated files clean: FORCE @@ -141,8 +144,8 @@ diff-cover.html: coverage.xml diff-cover --compare-branch=main $^ --html-report $@ ## test : run the cwltest test suite -test: $(PYSOURCES) all - python setup.py test ${PYTEST_EXTRA} +test: $(PYSOURCES) + python -m pytest -rs ${PYTEST_EXTRA} ## testcov : run the cwltest test suite and collect coverage testcov: $(PYSOURCES) @@ -161,21 +164,9 @@ list-author-emails: mypy3: mypy mypy: $(filter-out setup.py gittagger.py,$(PYSOURCES)) - if ! test -f $(shell python3 -c 'import ruamel.yaml; import os.path; print(os.path.dirname(ruamel.yaml.__file__))')/py.typed ; \ - then \ - rm -Rf mypy-stubs/ruamel/yaml ; \ - ln -s $(shell python3 -c 'import ruamel.yaml; import os.path; print(os.path.dirname(ruamel.yaml.__file__))') \ - mypy-stubs/ruamel/ ; \ - fi # if minimally required ruamel.yaml version is 0.15.99 or greater, than the above can be removed MYPYPATH=$$MYPYPATH:mypy-stubs mypy $^ mypy_3.6: $(filter-out setup.py gittagger.py,$(PYSOURCES)) - if ! test -f $(shell python3 -c 'import ruamel.yaml; import os.path; print(os.path.dirname(ruamel.yaml.__file__))')/py.typed ; \ - then \ - rm -Rf mypy-stubs/ruamel/yaml ; \ - ln -s $(shell python3 -c 'import ruamel.yaml; import os.path; print(os.path.dirname(ruamel.yaml.__file__))') \ - mypy-stubs/ruamel/ ; \ - fi # if minimally required ruamel.yaml version is 0.15.99 or greater, than the above can be removed MYPYPATH=$$MYPYPATH:mypy-stubs mypy --python-version 3.6 $^ pyupgrade: $(filter-out schema_salad/metaschema.py,$(PYSOURCES)) @@ -187,8 +178,8 @@ release-test: FORCE release: release-test . testenv2/bin/activate && \ - python testenv2/src/${PACKAGE}/setup.py sdist bdist_wheel - . testenv2/bin/activate && \ + pip install build && \ + python -m build testenv2/src/${PACKAGE} && \ pip install twine && \ twine upload testenv2/src/${PACKAGE}/dist/* && \ git tag ${VERSION} && git push --tags diff --git a/dev-requirements.txt b/dev-requirements.txt new file mode 100644 index 0000000..3b58070 --- /dev/null +++ b/dev-requirements.txt @@ -0,0 +1,14 @@ +diff_cover +black +pylint +pep257 +pydocstyle +flake8 +tox < 4 +tox-pyenv +isort +wheel +autoflake +flake8-bugbear +pyupgrade +bandit diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d4bb2cb --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/_static/favicon.ico b/docs/_static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..9fadc9a7c992f41b5c8730b34cf60871378c8f56 GIT binary patch literal 15086 zcmeHO`BPL^7VfE;KOjHP%2Xu9WF{pI%_6cRbP#$J9Rm_jVM-8GEFmtHk+^|EWE@eW zsEH`S8BIARM#I|B(DX(S5Ja$98xTP@WoZ@>zd5(tM>$lH6i(&&Ue(;H)Azl8uls)I z-uuqI=R4;~BtMhLmPjNvHZRZLl1SR=ySJ!j*SGvaA~`}g*wH=o z6UinL_PwPnu~x5s0;nbtYq>|jUx*d_PmTNe%nQtth_TE}&!Q;13(Cvgn3)!r4h(z# z#ZK&Ap~D`3Jqj;%Vdj}QbYM912zw%7-{GaT2s<|9Jr?{lV%WdS?nHv07V(}H*y>e* zIQI%W;hd0;YVcWQ%u`_VvBQr=#xQlR?QbaCSStP*%sv;#bNjHvjO5ML_`szE zVarMp=30u4KIQl}w-am~5JTy1AIIM4Dug&G@fX(;taVXhy_X8#lG?^N(^jlgC9fV%9F@cX^E6LR-2A$|J<9N$id{crXo$TbaGRg>_sE4v~0{0a{5 zWI<+|345EP2y#0CZCSGju=haja}y4Bmmsq{2Ztq@P`$IdBRaAi_I6hx zd-w7j{?i$1yb#CM2YTIODCD;wecAtx)c^8jpFx?|DER*802*|?P^`EPsjYSXGyCH& z%YgE`2JRNY*9L756uwvH><_d5{?b$^Z`TPPI|tC9>4w7lBH16S{g?h~H&#dwL0Qnw z-6Hr}UtvP9=UI#Wcl=#4r0;x=0N-Mi6!!`qI|tC9X@|n&44nRu16OH2oN52F(ys(1 zMdHw*w`T$|5fxZ&pAQe(d%DvejvXIQYZSaM(`7OvF}4cc4u$X`AHX8ALZlzKhmohx zxFHf`&HS$&QI+r`?96xZC;v-Me%Og4jTjr95hP{~l=1!uwngaiKIc0U{$ST)oXvOu z^SH3FH`F{qe5j6m_o6x9J;Y6kizk~gIq{rRQIK_wZV>Tnv{+5t$y!$>))03RM%>B2 z&b48BYF3b#IZ%wBI+N0bwS@fx;;uqT))9}jEAo2`^i6TM3A$!D({|QjJ@Ibg#2qq; zATIIjp(czGzbJ+>&^w7^iFJr1>>G){<>Ug54dY0~PzHOaa6G9V(Zoal)q{k%XeQZ5 zjW7$`c5?m8bjVD)hZuKj93b{(JRm2n8RjwZjKis<2E=<<<1kw-@fZ!ReA`dfX%20ahm z(4#4wOKd=LP$l%=_KC))e^rgahm&a34vQw9^eXnB_*f(i&4Rt4TkwkTFI2yp3-teE z{(FGsY1xo?lg#C5Q7+f~LR0BY22FeK*_zP?MHszCSr(BpV%hgB@t%9-oDKF|Xf9~c*6JmWT5am{eJ?kpbc;^W( zZL>zECT4Le`98v#FGg}8wi-kI{Q8l@{nJSQs19qLDVKqK*|c4Cyki)AJcUC$YY{|z zMlkU(DZB1sXkePRabOMg_f2Bojv53|`zweOIzSi(c^-@AreUlJAP$r9mrL_;{uF=l zxUtb`r0y$#vn_G)c3&bYLWfr3_xLDdqtB3qF0_vfn8>ky+RNxK&zo82RaQZcZ8NpJI1-rG<~);8BK48O@j&=a;lwhh#daAJPfKUb!A>@*DDD*Wi}jrpeiv}=LAKTd^Z5Y2&lyj_XbBsV zIi7;vHJe`u?t%dd_Ab(oypOb?abWKN6<+Rw>e}M>FpPU({%B&b9)|qI=WjA!I-Bh0 z=D-Tn>R)gF!s0e3QyUQ-qQRZl{11()1HQ7W$UN4#=;yb#`Z3l8=HTOm8yFs%{O{TI zBWIJ7v)H+{jB<~^Ky%aL`;Yy7{oQ_q2IXK+{8tzne7$wppy`CK(-ov2u3vQi35&s= zr2L5w6>6wU7N-Nt+rMzki1pqoXczfgu4^>~eMnH~aP70#kH=RQ^<(d= 2.2 +sphinx-rtd-theme==1.1.1 +sphinx-autoapi +sphinx-autodoc-typehints +typed_ast;python_version<'3.8' +sphinxcontrib-autoprogram diff --git a/release-test.sh b/release-test.sh index e840392..42684e0 100755 --- a/release-test.sh +++ b/release-test.sh @@ -19,7 +19,7 @@ else fi run_tests="bin/py.test --pyargs ${module}" pipver=20.3.3 # minimum required version of pip for Python 3.10 -setuptoolsver=50.0.0 # required for Python 3.10 +setuptoolsver=50.0.1 # required for Python 3.10 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" rm -Rf testenv? || /bin/true @@ -63,7 +63,7 @@ rm -f lib/python-wheels/setuptools* \ # The following can fail if you haven't pushed your commits to ${repo} pip install -e "git+${repo}@${HEAD}#egg=${package}${extras}" pushd src/${package} -pip install -rtest-requirements.txt +pip install -rtest-requirements.txt build make dist make test cp dist/${package}*tar.gz ../../../testenv3/ @@ -84,7 +84,7 @@ rm -f lib/python-wheels/setuptools* \ && pip install --force-reinstall -U pip==${pipver} \ && pip install setuptools==${setuptoolsver} wheel package_tar=$(find . -name "${package}*tar.gz") -pip install "-r${DIR}/test-requirements.txt" +pip install "-r${DIR}/test-requirements.txt" build pip install "${package_tar}${extras}" mkdir out tar --extract --directory=out -z -f ${package}*.tar.gz From af433f71f5236b8a57deb724a362a2e3e1a66af3 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" <1330696+mr-c@users.noreply.github.com> Date: Sun, 8 Jan 2023 20:26:06 +0100 Subject: [PATCH 055/165] cwltest plugin for pytest (#74) Co-authored-by: GlassOfWhiskey --- .coveragerc | 18 +- Makefile | 14 +- README.rst | 16 +- cwltest/__init__.py | 2 +- cwltest/argparser.py | 9 +- cwltest/compare.py | 164 +++++ cwltest/hooks.py | 23 + cwltest/main.py | 342 +++------- cwltest/plugin.py | 393 ++++++++++++ cwltest/utils.py | 587 ++++++++++++------ docs/conf.py | 4 +- docs/index.rst | 14 +- docs/pytest.rst | 174 ++++++ gittaggers.py | 1 + mypy-requirements.txt | 2 + .../defusedxml/{__init__.py => __init__.pyi} | 0 .../ruamel/{__init__.py => __init__.pyi} | 0 release-test.sh | 2 +- requirements.txt | 3 +- setup.py | 27 +- test-requirements.txt | 5 +- .../conformance_test_v1.0.cwltest.yml | 17 + .../conformance_test_v1.2.cwltest.yaml | 15 + tests/test-data/cwltool-conftest.py | 37 ++ tests/test-data/v1.0/args.py | 7 + tests/test-data/v1.0/cat-job.json | 6 + tests/test-data/v1.0/cat-n-job.json | 7 + tests/test-data/v1.0/cat1-testcli.cwl | 45 ++ tests/test-data/v1.0/hello.txt | 1 + tests/test_categories.py | 8 +- tests/test_compare.py | 413 +++++++++++- tests/test_plugin.py | 126 ++++ tests/util.py | 6 +- tox.ini | 21 +- 34 files changed, 1986 insertions(+), 523 deletions(-) create mode 100644 cwltest/compare.py create mode 100644 cwltest/hooks.py create mode 100644 cwltest/plugin.py create mode 100644 docs/pytest.rst rename mypy-stubs/defusedxml/{__init__.py => __init__.pyi} (100%) rename mypy-stubs/ruamel/{__init__.py => __init__.pyi} (100%) create mode 100644 tests/test-data/conformance_test_v1.0.cwltest.yml create mode 100644 tests/test-data/conformance_test_v1.2.cwltest.yaml create mode 100644 tests/test-data/cwltool-conftest.py create mode 100644 tests/test-data/v1.0/args.py create mode 100644 tests/test-data/v1.0/cat-n-job.json create mode 100644 tests/test-data/v1.0/cat1-testcli.cwl create mode 100644 tests/test-data/v1.0/hello.txt create mode 100644 tests/test_plugin.py diff --git a/.coveragerc b/.coveragerc index 020763e..6086f7f 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,7 +1,15 @@ +[paths] +source = + cwltest + */site-packages/cwltest + */cwltest + [run] branch = True -source = cwltest -omit = tests/* +source_pkgs = cwltest +omit = + tests/* + */site-packages/cwltest/tests/* [report] exclude_lines = @@ -9,5 +17,9 @@ exclude_lines = pragma: no cover raise NotImplementedError if __name__ == .__main__.: + if TYPE_CHECKING: + \.\.\. ignore_errors = True -omit = tests/* +omit = + tests/* + */site-packages/cwltest/tests/* diff --git a/Makefile b/Makefile index 9ff55a8..2c7d049 100644 --- a/Makefile +++ b/Makefile @@ -76,7 +76,7 @@ docs: FORCE clean: FORCE rm -f ${MODILE}/*.pyc tests/*.pyc python setup.py clean --all || true - rm -Rf .coverage + rm -Rf .coverage\.* .coverage rm -f diff-cover.html # Linting and code style related targets @@ -104,11 +104,11 @@ codespell: codespell -w $(shell git ls-files | grep -v mypy-stubs | grep -v gitignore) ## format : check/fix all code indentation and formatting (runs black) -format: - black setup.py setup.py cwltest tests mypy-stubs +format: $(PYSOURCES) mypy-stubs + black $^ -format-check: - black --diff --check setup.py cwltest tests mypy-stubs +format-check: $(PYSOURCES) mypy-stubs + black --diff --check $^ ## pylint : run static code analysis on Python code pylint: $(PYSOURCES) @@ -123,7 +123,9 @@ diff_pylint_report: pylint_report.txt diff-quality --compare-branch=main --violations=pylint pylint_report.txt .coverage: $(PYSOURCES) - python setup.py test --addopts "--cov --cov-config=.coveragerc --cov-report= ${PYTEST_EXTRA}" + COV_CORE_SOURCE=cwltest COV_CORE_CONFIG=.coveragerc COV_CORE_DATAFILE=.coverage \ + python -m pytest --cov --cov-append --cov-report= + # https://pytest-cov.readthedocs.io/en/latest/plugins.html#plugin-coverage coverage.xml: .coverage coverage xml diff --git a/README.rst b/README.rst index 15066a6..f6e7e2e 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,6 @@ -========================================== +########################################## Common Workflow Language testing framework -========================================== +########################################## |Linux Build Status| |Code coverage| @@ -34,8 +34,12 @@ conformance tests. This is written and tested for Python 3.6, 3.7, 3.8, 3.9, 3.10, and 3.11. +.. contents:: Table of Contents + :local: + +******* Install -------- +******* Installing the official package from PyPi @@ -56,15 +60,17 @@ Or from source git clone https://github.com/common-workflow-language/cwltest.git cd cwltest && python setup.py install +*********************** Run on the command line ------------------------ +*********************** Simple command:: cwltest --test test-descriptions.yml --tool cwl-runner +***************************************** Generate conformance badges using cwltest ------------------------------------------ +***************************************** To make badges that show the results of the conformance test, you can generate JSON files for https://badgen.net by using --badgedir option diff --git a/cwltest/__init__.py b/cwltest/__init__.py index 5b6419f..fa05598 100755 --- a/cwltest/__init__.py +++ b/cwltest/__init__.py @@ -1,4 +1,4 @@ -"""Common Workflow Language testing framework.""" +"""Run CWL descriptions with a cwl-runner, and look for expected output.""" import logging import threading diff --git a/cwltest/argparser.py b/cwltest/argparser.py index b567622..6cc616d 100644 --- a/cwltest/argparser.py +++ b/cwltest/argparser.py @@ -7,7 +7,7 @@ from cwltest import DEFAULT_TIMEOUT -def arg_parser(): # type: () -> argparse.ArgumentParser +def arg_parser() -> argparse.ArgumentParser: """Generate a command Line argument parser for cwltest.""" parser = argparse.ArgumentParser( description="Common Workflow Language testing framework" @@ -60,7 +60,8 @@ def arg_parser(): # type: () -> argparse.ArgumentParser parser.add_argument( "--junit-verbose", action="https://github.com/store_true", - help="Store more verbose output to JUnit xml file", + help="Store more verbose output to JUnit XML file by not passing " + "'--quiet' to the CWL runner.", ) parser.add_argument( "--test-arg", @@ -101,7 +102,9 @@ def arg_parser(): # type: () -> argparse.ArgumentParser ), ) parser.add_argument( - "--badgedir", type=str, help="Directory that stores JSON files for badges." + "--badgedir", + type=str, + help="Create JSON badges and store them in this directory.", ) pkg = pkg_resources.require("cwltest") diff --git a/cwltest/compare.py b/cwltest/compare.py new file mode 100644 index 0000000..b56a7c3 --- /dev/null +++ b/cwltest/compare.py @@ -0,0 +1,164 @@ +"""Compare utilities for CWL objects.""" + +import json +from typing import Any, Dict, Set + + +class CompareFail(Exception): + """Compared CWL objects are not equal.""" + + @classmethod + def format(cls, expected, actual, cause=None): + # type: (Any, Any, Any) -> CompareFail + """Load the difference details into the error message.""" + message = "expected: {}\ngot: {}".format( + json.dumps(expected, indent=4, sort_keys=True), + json.dumps(actual, indent=4, sort_keys=True), + ) + if cause: + message += "\ncaused by: %s" % cause + return cls(message) + + +def _check_keys(keys, expected, actual): + # type: (Set[str], Dict[str,Any], Dict[str,Any]) -> None + for k in keys: + try: + compare(expected.get(k), actual.get(k)) + except CompareFail as e: + raise CompareFail.format( + expected, actual, f"field '{k}' failed comparison: {str(e)}" + ) from e + + +def _compare_contents(expected, actual): + # type: (Dict[str,Any], Dict[str,Any]) -> None + expected_contents = expected["contents"] + with open(actual["path"]) as f: + actual_contents = f.read() + if expected_contents != actual_contents: + raise CompareFail.format( + expected, + actual, + json.dumps( + "Output file contents do not match: actual '%s' is not equal to expected '%s'" + % (actual_contents, expected_contents) + ), + ) + + +def _compare_dict(expected, actual): + # type: (Dict[str,Any], Dict[str,Any]) -> None + for c in expected: + try: + compare(expected[c], actual.get(c)) + except CompareFail as e: + raise CompareFail.format( + expected, actual, f"failed comparison for key '{c}': {e}" + ) from e + extra_keys = set(actual.keys()).difference(list(expected.keys())) + for k in extra_keys: + if actual[k] is not None: + raise CompareFail.format(expected, actual, "unexpected key '%s'" % k) + + +def _compare_directory(expected, actual): + # type: (Dict[str,Any], Dict[str,Any]) -> None + if actual.get("class") != "Directory": + raise CompareFail.format( + expected, actual, "expected object with a class 'Directory'" + ) + if "listing" not in actual: + raise CompareFail.format( + expected, actual, "'listing' is mandatory field in Directory object" + ) + for i in expected["listing"]: + found = False + for j in actual["listing"]: + try: + compare(i, j) + found = True + break + except CompareFail: + pass + if not found: + raise CompareFail.format( + expected, + actual, + "%s not found" % json.dumps(i, indent=4, sort_keys=True), + ) + _compare_file(expected, actual) + + +def _compare_file(expected, actual): + # type: (Dict[str,Any], Dict[str,Any]) -> None + _compare_location(expected, actual) + if "contents" in expected: + _compare_contents(expected, actual) + other_keys = set(expected.keys()) - {"path", "location", "listing", "contents"} + _check_keys(other_keys, expected, actual) + _check_keys(other_keys, expected, actual) + + +def _compare_location(expected, actual): + # type: (Dict[str,Any], Dict[str,Any]) -> None + if "path" in expected: + comp = "path" + if "path" not in actual: + actual["path"] = actual["location"] + elif "location" in expected: + comp = "location" + else: + return + if actual.get("class") == "Directory": + actual[comp] = actual[comp].rstrip("/") + + if expected[comp] != "Any" and ( + not ( + actual[comp].endswith("/" + expected[comp]) + or ("/" not in actual[comp] and expected[comp] == actual[comp]) + ) + ): + raise CompareFail.format( + expected, + actual, + f"{actual[comp]} does not end with {expected[comp]}", + ) + + +def compare(expected, actual): # type: (Any, Any) -> None + """Compare two CWL objects.""" + if expected == "Any": + return + if expected is not None and actual is None: + raise CompareFail.format(expected, actual) + + try: + if isinstance(expected, dict): + if not isinstance(actual, dict): + raise CompareFail.format(expected, actual) + + if expected.get("class") == "File": + _compare_file(expected, actual) + elif expected.get("class") == "Directory": + _compare_directory(expected, actual) + else: + _compare_dict(expected, actual) + + elif isinstance(expected, list): + if not isinstance(actual, list): + raise CompareFail.format(expected, actual) + + if len(expected) != len(actual): + raise CompareFail.format(expected, actual, "lengths don't match") + for c in range(0, len(expected)): + try: + compare(expected[c], actual[c]) + except CompareFail as e: + raise CompareFail.format(expected, actual, e) from e + else: + if expected != actual: + raise CompareFail.format(expected, actual) + + except Exception as e: + raise CompareFail(str(e)) from e diff --git a/cwltest/hooks.py b/cwltest/hooks.py new file mode 100644 index 0000000..9b3faae --- /dev/null +++ b/cwltest/hooks.py @@ -0,0 +1,23 @@ +"""Hooks for pytest-cwl users.""" + +from typing import Any, Dict, Optional, Tuple + +from cwltest import utils + + +def pytest_cwl_execute_test( # type: ignore[empty-body] + config: utils.CWLTestConfig, processfile: str, jobfile: Optional[str] +) -> Tuple[int, Optional[Dict[str, Any]]]: + """ + Execute CWL test using a Python function instead of a command line runner. + + The return value is a tuple. + - status code + - 0 = success + - :py:attr:`cwltest.UNSUPPORTED_FEATURE` for an unsupported feature + - and any other number for failure + - CWL output object using plain Python objects. + + :param processfile: a path to a CWL document + :param jobfile: an optionl path to JSON/YAML input object + """ diff --git a/cwltest/main.py b/cwltest/main.py index 3652764..6c9d293 100644 --- a/cwltest/main.py +++ b/cwltest/main.py @@ -2,201 +2,71 @@ """Entry point for cwltest.""" import argparse -import json import os -import shlex -import shutil -import subprocess # nosec import sys -import time from collections import defaultdict from concurrent.futures import ThreadPoolExecutor -from typing import Any, Dict, List, Optional, Set, Union +from typing import Dict, List, Optional, Set, cast import junit_xml -import pkg_resources -import ruamel.yaml.scanner import schema_salad.avro import schema_salad.ref_resolver import schema_salad.schema -from rdflib import Graph - -from cwltest import REQUIRED, UNSUPPORTED_FEATURE, logger, utils from cwltest.argparser import arg_parser -from cwltest.utils import TestResult +from cwltest.utils import CWLTestConfig, TestResult +from schema_salad.exceptions import ValidationException +from cwltest import logger, utils -def _run_test( - args, # type: argparse.Namespace - test, # type: Dict[str, str] - test_number, # type: int - total_tests, # type: int - timeout, # type: int - junit_verbose=False, # type: bool - verbose=False, # type: bool -): # type: (...) -> TestResult - out = {} # type: Dict[str,Any] - outdir = outstr = outerr = "" - test_command = [] # type: List[str] - duration = 0.0 - process = None # type: Optional[subprocess.Popen[str]] - prefix = "" - suffix = "" - if sys.stderr.isatty(): - prefix = "\r" - else: - suffix = "\n" - try: - cwd = os.getcwd() - test_command = utils.prepare_test_command( - args.tool, args.args, args.testargs, test, cwd, junit_verbose - ) +if sys.stderr.isatty(): + PREFIX = "\r" + SUFFIX = "" +else: + PREFIX = "" + SUFFIX = "\n" - if test.get("short_name"): - sys.stderr.write( - "%sTest [%i/%i] %s: %s%s\n" - % ( - prefix, - test_number, - total_tests, - test.get("short_name"), - test.get("doc", "").replace("\n", " ").strip(), - suffix, - ) - ) - else: - sys.stderr.write( - "%sTest [%i/%i] %s%s\n" - % ( - prefix, - test_number, - total_tests, - test.get("doc", "").replace("\n", " ").strip(), - suffix, - ) - ) - if verbose: - sys.stderr.write(f"Running: {' '.join(test_command)}\n") - sys.stderr.flush() - start_time = time.time() - stderr = subprocess.PIPE if not args.verbose else None - process = subprocess.Popen( # nosec - test_command, - stdout=subprocess.PIPE, - stderr=stderr, - universal_newlines=True, - cwd=cwd, - ) - outstr, outerr = process.communicate(timeout=timeout) - return_code = process.poll() - duration = time.time() - start_time - if return_code: - raise subprocess.CalledProcessError(return_code, " ".join(test_command)) - - out = json.loads(outstr) - except ValueError as err: - logger.error(str(err)) - logger.error(outstr) - logger.error(outerr) - except subprocess.CalledProcessError as err: - if err.returncode == UNSUPPORTED_FEATURE and REQUIRED not in test.get( - "tags", ["required"] - ): - return utils.TestResult( - UNSUPPORTED_FEATURE, outstr, outerr, duration, args.classname +def _run_test( + args: argparse.Namespace, + test: Dict[str, str], + test_number: int, + total_tests: int, +) -> TestResult: + if test.get("short_name"): + sys.stderr.write( + "%sTest [%i/%i] %s: %s%s\n" + % ( + PREFIX, + test_number, + total_tests, + test.get("short_name"), + test.get("doc", "").replace("\n", " ").strip(), + SUFFIX, ) - if test.get("should_fail", False): - return utils.TestResult(0, outstr, outerr, duration, args.classname) - logger.error( - """Test %i failed: %s""", - test_number, - " ".join([shlex.quote(tc) for tc in test_command]), ) - logger.error(test.get("doc", "").replace("\n", " ").strip()) - if err.returncode == UNSUPPORTED_FEATURE: - logger.error("Does not support required feature") - else: - logger.error("Returned non-zero") - logger.error(outerr) - return utils.TestResult(1, outstr, outerr, duration, args.classname, str(err)) - except (ruamel.yaml.scanner.ScannerError, TypeError) as err: - logger.error( - """Test %i failed: %s""", - test_number, - " ".join([shlex.quote(tc) for tc in test_command]), - ) - logger.error(outstr) - logger.error("Parse error %s", str(err)) - logger.error(outerr) - except KeyboardInterrupt: - logger.error( - """Test %i interrupted: %s""", - test_number, - " ".join([shlex.quote(tc) for tc in test_command]), - ) - raise - except subprocess.TimeoutExpired: - logger.error( - """Test %i timed out: %s""", - test_number, - " ".join([shlex.quote(tc) for tc in test_command]), - ) - logger.error(test.get("doc", "").replace("\n", " ").strip()) - # Kill and re-communicate to get the logs and reap the child, as - # instructed in the subprocess docs. - if process: - process.kill() - outstr, outerr = process.communicate() - return utils.TestResult( - 2, outstr, outerr, timeout, args.classname, "Test timed out" - ) - finally: - if process is not None and process.returncode is None: - logger.error("""Terminating lingering process""") - process.terminate() - for _ in range(0, 3): - time.sleep(1) - if process.poll() is not None: - break - if process.returncode is None: - process.kill() - - fail_message = "" - - if test.get("should_fail", False): - logger.warning( - """Test %i failed: %s""", - test_number, - " ".join([shlex.quote(tc) for tc in test_command]), - ) - logger.warning(test.get("doc", "").replace("\n", " ").strip()) - logger.warning("Returned zero but it should be non-zero") - return utils.TestResult(1, outstr, outerr, duration, args.classname) - - try: - utils.compare(test.get("output"), out) - except utils.CompareFail as ex: - logger.warning( - """Test %i failed: %s""", - test_number, - " ".join([shlex.quote(tc) for tc in test_command]), + else: + sys.stderr.write( + "%sTest [%i/%i] %s%s\n" + % ( + PREFIX, + test_number, + total_tests, + test.get("doc", "").replace("\n", " ").strip(), + SUFFIX, + ) ) - logger.warning(test.get("doc", "").replace("\n", " ").strip()) - logger.warning("Compare failure %s", ex) - fail_message = str(ex) - - if outdir: - shutil.rmtree(outdir, True) - - return utils.TestResult( - (1 if fail_message else 0), - outstr, - outerr, - duration, - args.classname, - fail_message, + sys.stderr.flush() + config = CWLTestConfig( + basedir=args.basedir, + classname=args.classname, + tool=args.tool, + args=args.args, + testargs=args.testargs, + timeout=args.timeout, + verbose=args.verbose, + runner_quiet=not args.junit_verbose, ) + return utils.run_test_plain(config, test, test_number) def _expand_number_range(nr: str) -> List[int]: @@ -226,34 +96,17 @@ def main() -> int: arg_parser().print_help() return 1 - schema_resource = pkg_resources.resource_stream(__name__, "cwltest-schema.yml") - cache = { - "https://w3id.org/cwl/cwltest/cwltest-schema.yml": schema_resource.read().decode( - "utf-8" - ) - } # type: Optional[Dict[str, Union[str, Graph, bool]]] - (document_loader, avsc_names, _, _,) = schema_salad.schema.load_schema( - "https://w3id.org/cwl/cwltest/cwltest-schema.yml", cache=cache - ) - - if not isinstance(avsc_names, schema_salad.avro.schema.Names): - print(avsc_names) + try: + tests, metadata = utils.load_and_validate_tests(args.test) + except ValidationException: return 1 - tests, metadata = schema_salad.schema.load_and_validate( - document_loader, avsc_names, args.test, True - ) - failures = 0 unsupported = 0 - passed = 0 suite_name, _ = os.path.splitext(os.path.basename(args.test)) - report = junit_xml.TestSuite(suite_name, []) + report: Optional[junit_xml.TestSuite] = junit_xml.TestSuite(suite_name, []) - # the number of total tests, failed tests, unsupported tests and passed tests for each tag ntotal = defaultdict(int) # type: Dict[str, int] - nfailures = defaultdict(int) # type: Dict[str, int] - nunsupported = defaultdict(int) # type: Dict[str, int] npassed = defaultdict(int) # type: Dict[str, int] if args.only_tools: @@ -269,22 +122,12 @@ def main() -> int: raise Exception("Unexpected code path.") if args.tags: - alltests = tests - tests = [] - tags = args.tags.split(",") - for t in alltests: - ts = t.get("tags", []) - if any(tag in ts for tag in tags): - tests.append(t) + tags = set(args.tags.split(",")) + tests = [t for t in tests if tags.intersection(t.get("tags", []))] if args.exclude_tags: - ex_tests = [] - tags = args.exclude_tags.split(",") - for t in tests: - ts = t.get("tags", []) - if all(tag not in ts for tag in tags): - ex_tests.append(t) - tests = ex_tests + tags = set(args.exclude_tags.split(",")) + tests = [t for t in tests if not tags.intersection(t.get("tags", []))] for t in tests: if t.get("label"): @@ -363,49 +206,23 @@ def main() -> int: tests[i], i + 1, len(tests), - args.timeout, - args.junit_verbose, - args.verbose, ) for i in ntest ] try: - for i, job in zip(ntest, jobs): - test_result = job.result() - test_case = test_result.create_test_case(tests[i]) - test_case.url = f"cwltest:{suite_name}#{i + 1}" - total += 1 - tags = tests[i].get("tags", []) - for t in tags: - ntotal[t] += 1 - - return_code = test_result.return_code - category = test_case.category - if return_code == 0: - passed += 1 - for t in tags: - npassed[t] += 1 - elif return_code != UNSUPPORTED_FEATURE: - failures += 1 - for t in tags: - nfailures[t] += 1 - test_case.add_failure_info(output=test_result.message) - elif return_code == UNSUPPORTED_FEATURE and category == REQUIRED: - failures += 1 - for t in tags: - nfailures[t] += 1 - test_case.add_failure_info(output=test_result.message) - elif category != REQUIRED and return_code == UNSUPPORTED_FEATURE: - unsupported += 1 - for t in tags: - nunsupported[t] += 1 - test_case.add_skipped_info("Unsupported") - else: - raise Exception( - "This is impossible, return_code: {}, category: " - "{}".format(return_code, category) - ) - report.test_cases.append(test_case) + ( + total, + passed, + failures, + unsupported, + ntotal, + npassed, + nfailures, + nunsupported, + report, + ) = utils.parse_results( + (job.result() for job in jobs), tests, suite_name, report + ) except KeyboardInterrupt: for job in jobs: job.cancel() @@ -413,29 +230,10 @@ def main() -> int: if args.junit_xml: with open(args.junit_xml, "w") as xml: - junit_xml.to_xml_report_file(xml, [report]) + junit_xml.to_xml_report_file(xml, [cast(junit_xml.TestSuite, report)]) if args.badgedir: - os.mkdir(args.badgedir) - for t, v in ntotal.items(): - percent = int((npassed[t] / float(v)) * 100) - if npassed[t] == v: - color = "green" - elif t == "required": - color = "red" - else: - color = "yellow" - - with open(f"{args.badgedir}/{t}.json", "w") as out: - out.write( - json.dumps( - { - "subject": f"{t}", - "status": f"{percent}%", - "color": color, - } - ) - ) + utils.generate_badges(args.badgedir, ntotal, npassed) if failures == 0 and unsupported == 0: logger.info("All tests passed") diff --git a/cwltest/plugin.py b/cwltest/plugin.py new file mode 100644 index 0000000..c642519 --- /dev/null +++ b/cwltest/plugin.py @@ -0,0 +1,393 @@ +"""Discovers CWL test files and converts them to pytest.Items.""" +import argparse +import json +import os +import time +import traceback +from io import StringIO +from pathlib import Path +from typing import ( + Any, + Dict, + Iterator, + List, + Optional, + Set, + TYPE_CHECKING, + Tuple, + Union, + cast, +) + +import pytest +from typing_extensions import Protocol + +from cwltest import REQUIRED, UNSUPPORTED_FEATURE, logger, utils +from cwltest.compare import CompareFail, compare + +if TYPE_CHECKING: + from _pytest._code.code import ExceptionInfo, _TracebackStyle + from _pytest.compat import LEGACY_PATH + from _pytest.config import Config + from _pytest.config import Config as PytestConfig + from _pytest.config import PytestPluginManager + from _pytest.config.argparsing import Parser as PytestParser + from _pytest.nodes import Node + + +class TestRunner(Protocol): + """Protocol to type-check test runner functions via the pluggy hook.""" + + def __call__( + self, config: utils.CWLTestConfig, processfile: str, jobfile: Optional[str] + ) -> List[Optional[Dict[str, Any]]]: + """Type signature for pytest_cwl_execute_test hook results.""" + ... + + +def _get_comma_separated_option(config: "Config", name: str) -> List[str]: + options = config.getoption(name) + if options is None: + return [] + elif "," in options: + return [opt.strip() for opt in options.split(",")] + else: + return [options.strip()] + + +def _run_test_hook_or_plain( + test: Dict[str, str], + config: utils.CWLTestConfig, + hook: TestRunner, +) -> utils.TestResult: + """Run tests using a provided pytest_cwl_execute_test hook or the --cwl-runner.""" + processfile, jobfile = utils.prepare_test_paths(test, config.basedir) + start_time = time.time() + outerr = "" + hook_out = hook(config=config, processfile=processfile, jobfile=jobfile) + if not hook_out: + return utils.run_test_plain(config, test) + returncode, out = cast(Tuple[int, Optional[Dict[str, Any]]], hook_out[0]) + duration = time.time() - start_time + outstr = json.dumps(out) if out is not None else "{}" + if returncode == UNSUPPORTED_FEATURE: + if REQUIRED not in test.get("tags", ["required"]): + return utils.TestResult( + UNSUPPORTED_FEATURE, outstr, "", duration, config.classname + ) + elif returncode != 0: + if not bool(test.get("should_fail", False)): + logger.warning("Test failed unexpectedly: %s %s", processfile, jobfile) + logger.warning(test.get("doc")) + message = "Returned non-zero but it should be zero" + return utils.TestResult( + 1, outstr, outerr, duration, config.classname, message + ) + return utils.TestResult(0, outstr, outerr, duration, config.classname) + if bool(test.get("should_fail", False)): + return utils.TestResult( + 1, + outstr, + outerr, + duration, + config.classname, + "Test should failed, but it did not.", + ) + + fail_message = "" + + try: + compare(test.get("output"), out) + except CompareFail as ex: + logger.warning("""Test failed: %s %s""", processfile, jobfile) + logger.warning(test.get("doc")) + logger.warning("Compare failure %s", ex) + fail_message = str(ex) + + return utils.TestResult( + (1 if fail_message else 0), + outstr, + outerr, + duration, + config.classname, + fail_message, + ) + + +class CWLTestException(Exception): + """custom exception for error reporting.""" + + +class CWLItem(pytest.Item): + """A CWL test Item.""" + + def __init__( + self, + name: str, + parent: Optional["Node"], + spec: Dict[str, Any], + ) -> None: + """Initialize this CWLItem.""" + super().__init__(name, parent) + self.spec = spec + + def runtest(self) -> None: + """Execute using cwltest.""" + cwl_args = self.config.getoption("cwl_args") + config = utils.CWLTestConfig( + basedir=self.config.getoption("cwl_basedir"), + outdir=str( + self.config._tmp_path_factory.mktemp( # type: ignore[attr-defined] + self.spec.get("label", "unlabled_test") + ) + ), + tool=self.config.getoption("cwl_runner"), + args=cwl_args.split(" ") if cwl_args else None, + testargs=self.config.getoption("cwl_test_arg"), + timeout=self.config.getoption("timeout", None), + verbose=self.config.getoption("verbose", 0) >= 1, + runner_quiet=not self.config.getoption("cwl_runner_verbose", False), + ) + hook = self.config.hook.pytest_cwl_execute_test + result = _run_test_hook_or_plain( + self.spec, + config, + hook, + ) + cwl_results = self.config.cwl_results # type: ignore[attr-defined] + cast(List[Tuple[Dict[str, Any], utils.TestResult]], cwl_results).append( + (self.spec, result) + ) + if result.return_code != 0: + raise CWLTestException(self, result) + + def repr_failure( + self, + excinfo: "ExceptionInfo[BaseException]", + style: Optional["_TracebackStyle"] = None, + ) -> str: + """ + Document failure reason. + + Called when self.runtest() raises an exception. + """ + if isinstance(excinfo.value, CWLTestException): + from ruamel.yaml.main import YAML + + yaml = YAML() + result = excinfo.value.args[1] + stream = StringIO() + yaml.dump(self.spec, stream) + return "\n".join( + [ + "CWL test execution failed. ", + result.message, + f"Test: {stream.getvalue()}", + ] + ) + else: + return ( + f"{excinfo.type.__name__} occurred during CWL test execution:\n" + + "".join( + traceback.format_exception( + excinfo.type, excinfo.value, excinfo.traceback[0]._rawentry + ) + ) + ) + + def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str]: + """Status report.""" + return self.fspath, 0, "cwl test: %s" % self.name + + +class CWLYamlFile(pytest.File): + """A CWL test file.""" + + def _add_global_properties(self) -> None: + """Nonfunctional if xdist is installed and anything besides "-n 0" is used.""" + from _pytest.junitxml import xml_key + + xml = self.config._store.get(xml_key, None) + if xml: + xml.add_global_property("runner", self.config.getoption("cwl_runner")) + xml.add_global_property( + "runner_extra_args", self.config.getoption("cwl_args") + ) + + def collect(self) -> Iterator[CWLItem]: + """Load the cwltest file and yield parsed entries.""" + include: Set[str] = set(_get_comma_separated_option(self.config, "cwl_include")) + exclude: Set[str] = set(_get_comma_separated_option(self.config, "cwl_exclude")) + tags: Set[str] = set(_get_comma_separated_option(self.config, "cwl_tags")) + exclude_tags: Set[str] = set( + _get_comma_separated_option(self.config, "cwl_exclude_tags") + ) + tests, _ = utils.load_and_validate_tests(str(self.path)) + self._add_global_properties() + for entry in tests: + entry_tags = entry.get("tags", []) + if "label" in entry: + name = entry["label"] + elif "id" in entry: + name = utils.shortname(entry["id"]) + else: + name = entry.get("doc", "") + item = CWLItem.from_parent(self, name=name, spec=entry) + if include and name not in include: + item.add_marker( + pytest.mark.skip( + reason=f"Test '{name}' is not in the include list: {','.join(include)}." + ) + ) + elif exclude and name in exclude: + item.add_marker( + pytest.mark.skip(reason=f"Test '{name}' is in the exclude list.") + ) + elif tags and not tags.intersection(entry_tags): + item.add_marker( + pytest.mark.skip( + reason=f"Test '{name}' with tags {','.join(entry_tags)}" + f" doesn't have a tag on the allowed tag list: {','.join(tags)}." + ) + ) + elif exclude_tags and exclude_tags.intersection(entry_tags): + item.add_marker( + pytest.mark.skip( + reason=f"Test '{name}' has one or more tags on the exclusion " + f" tag list: {','.join(exclude_tags.intersection(entry_tags))}." + ) + ) + yield item + + +__OPTIONS: List[Tuple[str, Dict[str, Any]]] = [ + ( + "--cwl-runner", + { + "type": str, + "dest": "cwl_runner", + "default": "cwl-runner", + "help": "Name of the CWL runner to use.", + }, + ), + ( + "--cwl-runner-verbose", + { + "dest": "cwl_runner_verbose", + "default": False, + "action": "store_true", + "help": "If set, don't pass --quiet to the CWL runner.", + }, + ), + ( + "--cwl-badgedir", + { + "type": str, + "help": "Create badge JSON files and store them in this directory.", + }, + ), + ( + "--cwl-include", + { + "type": str, + "help": "Run specific CWL tests using their short names separated by comma", + }, + ), + ( + "--cwl-exclude", + { + "type": str, + "help": "Exclude specific CWL tests using their short names separated by comma", + }, + ), + ("--cwl-tags", {"type": str, "help": "Tags to be tested."}), + ("--cwl-exclude-tags", {"type": str, "help": "Tags not to be tested."}), + ( + "--cwl-args", + { + "type": str, + "help": "one or more arguments to pass first to tool runner (separated by spaces)", + }, + ), + ( + "--cwl-test-arg", + { + "type": str, + "help": "Additional argument given in test cases and required prefix for tool runner.", + "action": "append", + }, + ), + ( + "--cwl-basedir", + { + "help": "Basedir to use for tests", + "default": os.getcwd(), + }, + ), +] + + +def pytest_addoption(parser: "PytestParser") -> None: + """Add our options to the pytest command line.""" + for entry in __OPTIONS: + parser.addoption(entry[0], **entry[1]) + + +def _doc_options() -> argparse.ArgumentParser: + """Generate a stand-alone ArgumentParser to aid in documention.""" + parser = argparse.ArgumentParser("cwltest options for pytest.", add_help=False) + for entry in __OPTIONS: + parser.add_argument(entry[0], **entry[1]) + return parser + + +def pytest_collect_file( + file_path: Path, path: "LEGACY_PATH", parent: pytest.Collector +) -> Optional[pytest.Collector]: + """Is this file for us.""" + if ( + file_path.suffix == ".yml" or file_path.suffix == ".yaml" + ) and file_path.stem.endswith(".cwltest"): + return cast( + Optional[pytest.Collector], + CWLYamlFile.from_parent(parent, path=file_path), + ) + return None + + +def pytest_configure(config: "PytestConfig") -> None: + """Store the raw tests and the test results.""" + cwl_results: List[Tuple[Dict[str, Any], utils.TestResult]] = [] + config.cwl_results = cwl_results # type: ignore[attr-defined] + + +def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None: + """Generate badges.""" + cwl_results = cast( + List[Tuple[Dict[str, Any], utils.TestResult]], + getattr(session.config, "cwl_results", None), + ) + if not cwl_results: + return + tests, results = (list(item) for item in zip(*cwl_results)) + ( + total, + passed, + failures, + unsupported, + ntotal, + npassed, + nfailures, + nunsupported, + _, + ) = utils.parse_results(results, tests) + cwl_badgedir = session.config.getoption("cwl_badgedir") + if cwl_badgedir: + utils.generate_badges(cwl_badgedir, ntotal, npassed) + + +def pytest_addhooks(pluginmanager: "PytestPluginManager") -> None: + """Register our cwl hooks.""" + from cwltest import hooks + + pluginmanager.add_hookspecs(hooks) diff --git a/cwltest/utils.py b/cwltest/utils.py index 632e513..036fafb 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -1,14 +1,65 @@ import json import os import re +import shlex +import shutil +import subprocess # nosec import sys import tempfile -from typing import Any, Dict, List, Optional, Set, Text +import time +from collections import defaultdict +from typing import ( + Any, + Dict, + Iterable, + List, + MutableMapping, + MutableSequence, + Optional, + Tuple, + Union, + cast, +) import junit_xml +import pkg_resources +import ruamel.yaml.scanner +import schema_salad.avro import schema_salad.ref_resolver +import schema_salad.schema +from cwltest.compare import CompareFail, compare +from rdflib import Graph +from ruamel.yaml.scalarstring import ScalarString +from schema_salad.exceptions import ValidationException -from cwltest import REQUIRED, templock +from cwltest import REQUIRED, UNSUPPORTED_FEATURE, logger, templock + + +class CWLTestConfig(object): + """Store configuration values for cwltest.""" + + def __init__( + self, + basedir: Optional[str] = None, + outdir: Optional[str] = None, + classname: Optional[str] = None, + tool: Optional[str] = None, + args: Optional[List[str]] = None, + testargs: Optional[List[str]] = None, + timeout: Optional[int] = None, + verbose: Optional[bool] = None, + runner_quiet: Optional[bool] = None, + ) -> None: + """Initialize test configuration.""" + self.basedir: str = basedir or os.getcwd() + self.outdir: Optional[str] = outdir + self.classname: str = classname or "" + self.tool: str = tool or "cwl-runner" + self.args: List[str] = args or [] + self.testargs: List[str] = testargs or [] + self.timeout: Optional[int] = timeout + self.verbose: bool = verbose or False + self.runner_quiet: bool = runner_quiet or True class TestResult: @@ -16,14 +67,13 @@ class TestResult: def __init__( self, - return_code, - standard_output, - error_output, - duration, - classname, - message="", - ): - # type: (int, Text, Text, float, Text, str) -> None + return_code: int, + standard_output: str, + error_output: str, + duration: float, + classname: str, + message: str = "", + ) -> None: """Initialize a TestResult object.""" self.return_code = return_code self.standard_output = standard_output @@ -32,8 +82,8 @@ def __init__( self.message = message self.classname = classname - def create_test_case(self, test): - # type: (Dict[Text, Any]) -> junit_xml.TestCase + def create_test_case(self, test: Dict[str, Any]) -> junit_xml.TestCase: + """Create a jUnit XML test case from this test result.""" doc = test.get("doc", "N/A").strip() if test.get("tags"): category = ", ".join(test["tags"]) @@ -53,177 +103,186 @@ def create_test_case(self, test): return case -class CompareFail(Exception): - @classmethod - def format(cls, expected, actual, cause=None): - # type: (Any, Any, Any) -> CompareFail - message = "expected: {}\ngot: {}".format( - json.dumps(expected, indent=4, sort_keys=True), - json.dumps(actual, indent=4, sort_keys=True), - ) - if cause: - message += "\ncaused by: %s" % cause - return cls(message) - - -def compare_location(expected, actual): - # type: (Dict[str,Any], Dict[str,Any]) -> None - if "path" in expected: - comp = "path" - if "path" not in actual: - actual["path"] = actual["location"] - elif "location" in expected: - comp = "location" - else: - return - if actual.get("class") == "Directory": - actual[comp] = actual[comp].rstrip("/") - - if expected[comp] != "Any" and ( - not ( - actual[comp].endswith("/" + expected[comp]) - or ("/" not in actual[comp] and expected[comp] == actual[comp]) - ) - ): - raise CompareFail.format( - expected, - actual, - f"{actual[comp]} does not end with {expected[comp]}", - ) - - -def compare_contents(expected, actual): - # type: (Dict[str,Any], Dict[str,Any]) -> None - expected_contents = expected["contents"] - with open(actual["path"]) as f: - actual_contents = f.read() - if expected_contents != actual_contents: - raise CompareFail.format( - expected, - actual, - json.dumps( - "Output file contents do not match: actual '%s' is not equal to expected '%s'" - % (actual_contents, expected_contents) - ), - ) - +def _clean_ruamel(obj: Any) -> Any: + """Transform roundtrip loaded ruamel.yaml to plain objects.""" + if isinstance(obj, MutableMapping): + new_dict = {} + for k, v in obj.items(): + new_dict[str(k)] = _clean_ruamel(v) + return new_dict + if isinstance(obj, MutableSequence): + new_list = [] + for entry in obj: + new_list.append(_clean_ruamel(entry)) + return new_list + if isinstance(obj, ScalarString): + return str(obj) + for typ in int, float, bool, str: + if isinstance(obj, typ): + return typ(obj) + if obj is None: + return None + raise Exception(f"Unsupported type {type(obj)} of '{obj}'.") + + +def generate_badges( + badgedir: str, ntotal: Dict[str, int], npassed: Dict[str, int] +) -> None: + """Generate badges with conformance levels.""" + os.mkdir(badgedir) + for t, v in ntotal.items(): + percent = int((npassed[t] / float(v)) * 100) + if npassed[t] == v: + color = "green" + elif t == "required": + color = "red" + else: + color = "yellow" + + with open(f"{badgedir}/{t}.json", "w") as out: + out.write( + json.dumps( + { + "subject": f"{t}", + "status": f"{percent}%", + "color": color, + } + ) + ) -def check_keys(keys, expected, actual): - # type: (Set[str], Dict[str,Any], Dict[str,Any]) -> None - for k in keys: - try: - compare(expected.get(k), actual.get(k)) - except CompareFail as e: - raise CompareFail.format( - expected, actual, f"field '{k}' failed comparison: {str(e)}" - ) from e +def get_test_number_by_key( + tests: List[Dict[str, str]], key: str, value: str +) -> Optional[int]: + """Retrieve the test index from its name.""" + for i, test in enumerate(tests): + if key in test and test[key] == value: + return i + return None -def compare_file(expected, actual): - # type: (Dict[str,Any], Dict[str,Any]) -> None - compare_location(expected, actual) - if "contents" in expected: - compare_contents(expected, actual) - other_keys = set(expected.keys()) - {"path", "location", "listing", "contents"} - check_keys(other_keys, expected, actual) +def load_and_validate_tests(path: str) -> Tuple[Any, Dict[str, Any]]: + """ + Load and validate the given test file against the cwltest schema. -def compare_directory(expected, actual): - # type: (Dict[str,Any], Dict[str,Any]) -> None - if actual.get("class") != "Directory": - raise CompareFail.format( - expected, actual, "expected object with a class 'Directory'" + This also processes $import directives. + """ + schema_resource = pkg_resources.resource_stream(__name__, "cwltest-schema.yml") + cache: Optional[Dict[str, Union[str, Graph, bool]]] = { + "https://w3id.org/cwl/cwltest/cwltest-schema.yml": schema_resource.read().decode( + "utf-8" ) - if "listing" not in actual: - raise CompareFail.format( - expected, actual, "'listing' is mandatory field in Directory object" + } + (document_loader, avsc_names, _, _,) = schema_salad.schema.load_schema( + "https://w3id.org/cwl/cwltest/cwltest-schema.yml", cache=cache + ) + + if not isinstance(avsc_names, schema_salad.avro.schema.Names): + print(avsc_names) + raise ValidationException( + "Wrong instance for avsc_names: {}".format(type(avsc_names)) ) - for i in expected["listing"]: - found = False - for j in actual["listing"]: - try: - compare(i, j) - found = True - break - except CompareFail: - pass - if not found: - raise CompareFail.format( - expected, - actual, - "%s not found" % json.dumps(i, indent=4, sort_keys=True), - ) - compare_file(expected, actual) - - -def compare_dict(expected, actual): - # type: (Dict[str,Any], Dict[str,Any]) -> None - for c in expected: - try: - compare(expected[c], actual.get(c)) - except CompareFail as e: - raise CompareFail.format( - expected, actual, f"failed comparison for key '{c}': {e}" - ) from e - extra_keys = set(actual.keys()).difference(list(expected.keys())) - for k in extra_keys: - if actual[k] is not None: - raise CompareFail.format(expected, actual, "unexpected key '%s'" % k) - - -def compare(expected, actual): # type: (Any, Any) -> None - if expected == "Any": - return - if expected is not None and actual is None: - raise CompareFail.format(expected, actual) - - try: - if isinstance(expected, dict): - if not isinstance(actual, dict): - raise CompareFail.format(expected, actual) - - if expected.get("class") == "File": - compare_file(expected, actual) - elif expected.get("class") == "Directory": - compare_directory(expected, actual) - else: - compare_dict(expected, actual) - - elif isinstance(expected, list): - if not isinstance(actual, list): - raise CompareFail.format(expected, actual) - - if len(expected) != len(actual): - raise CompareFail.format(expected, actual, "lengths don't match") - for c in range(0, len(expected)): - try: - compare(expected[c], actual[c]) - except CompareFail as e: - raise CompareFail.format(expected, actual, e) from e - else: - if expected != actual: - raise CompareFail.format(expected, actual) - - except Exception as e: - raise CompareFail(str(e)) from e + tests, metadata = schema_salad.schema.load_and_validate( + document_loader, avsc_names, path, True + ) + tests = cast(List[Dict[str, Any]], _clean_ruamel(tests)) + + return tests, metadata + + +def parse_results( + results: Iterable[TestResult], + tests: List[Dict[str, Any]], + suite_name: Optional[str] = None, + report: Optional[junit_xml.TestSuite] = None, +) -> Tuple[ + int, # total + int, # passed + int, # failures + int, # unsupported + Dict[str, int], + Dict[str, int], + Dict[str, int], + Dict[str, int], + Optional[junit_xml.TestSuite], +]: + """ + Parse the results and return statistics and an optional report. -def get_test_number_by_key(tests, key, value): - # type: (List[Dict[str, str]], str, str) -> Optional[int] - for i, test in enumerate(tests): - if key in test and test[key] == value: - return i - return None + Returns the total number of tests, dictionary of test counts + (total, passed, failed, unsupported) by tag, and a jUnit XML report. + """ + total = 0 + passed = 0 + failures = 0 + unsupported = 0 + ntotal: Dict[str, int] = defaultdict(int) + nfailures: Dict[str, int] = defaultdict(int) + nunsupported: Dict[str, int] = defaultdict(int) + npassed: Dict[str, int] = defaultdict(int) + + for i, test_result in enumerate(results): + test_case = test_result.create_test_case(tests[i]) + test_case.url = ( + f"cwltest:{suite_name}#{i + 1}" + if suite_name is not None + else "cwltest:#{i + 1}" + ) + total += 1 + tags = tests[i].get("tags", []) + for t in tags: + ntotal[t] += 1 + + return_code = test_result.return_code + category = test_case.category + if return_code == 0: + passed += 1 + for t in tags: + npassed[t] += 1 + elif return_code != 0 and return_code != UNSUPPORTED_FEATURE: + failures += 1 + for t in tags: + nfailures[t] += 1 + test_case.add_failure_info(output=test_result.message) + elif return_code == UNSUPPORTED_FEATURE and category == REQUIRED: + failures += 1 + for t in tags: + nfailures[t] += 1 + test_case.add_failure_info(output=test_result.message) + elif category != REQUIRED and return_code == UNSUPPORTED_FEATURE: + unsupported += 1 + for t in tags: + nunsupported[t] += 1 + test_case.add_skipped_info("Unsupported") + else: + raise Exception( + "This is impossible, return_code: {}, category: " + "{}".format(return_code, category) + ) + if report: + report.test_cases.append(test_case) + return ( + total, + passed, + failures, + unsupported, + ntotal, + npassed, + nfailures, + nunsupported, + report, + ) def prepare_test_command( - tool, # type: str - args, # type: List[str] - testargs, # type: Optional[List[str]] - test, # type: Dict[str, Any] - cwd, # type: str - verbose=False, # type: bool -): # type: (...) -> List[str] + tool: str, + args: List[str], + testargs: Optional[List[str]], + test: Dict[str, Any], + cwd: str, + quiet: Optional[bool] = True, +) -> List[str]: """Turn the test into a command line.""" test_command = [tool] test_command.extend(args) @@ -248,26 +307,182 @@ def prepare_test_command( else: outdir = tempfile.mkdtemp() test_command.extend([f"--outdir={outdir}"]) - if not verbose: + if quiet: test_command.extend(["--quiet"]) + processfile, jobfile = prepare_test_paths(test, cwd) + test_command.extend([os.path.normcase(processfile)]) + if jobfile: + test_command.append(os.path.normcase(jobfile)) + return test_command + +def prepare_test_paths( + test: Dict[str, str], + cwd: str, +) -> Tuple[str, Optional[str]]: + """Determine the test path and the tool path.""" cwd = schema_salad.ref_resolver.file_uri(cwd) - toolpath = test["tool"] - if toolpath.startswith(cwd): - toolpath = toolpath[len(cwd) + 1 :] - test_command.extend([os.path.normcase(toolpath)]) - - jobpath = test.get("job") - if jobpath: - if jobpath.startswith(cwd): - jobpath = jobpath[len(cwd) + 1 :] - test_command.append(os.path.normcase(jobpath)) - return test_command + processfile = test["tool"] + if processfile.startswith(cwd): + processfile = processfile[len(cwd) + 1 :] + + jobfile = test.get("job") + if jobfile: + if jobfile.startswith(cwd): + jobfile = jobfile[len(cwd) + 1 :] + return processfile, jobfile + + +def run_test_plain( + config: CWLTestConfig, + test: Dict[str, str], + test_number: Optional[int] = None, +) -> TestResult: + """Plain test runner.""" + out: Dict[str, Any] = {} + outstr = outerr = "" + test_command: List[str] = [] + duration = 0.0 + number = "?" + if test_number is not None: + number = str(test_number) + process: Optional[subprocess.Popen[str]] = None + try: + cwd = os.getcwd() + test_command = prepare_test_command( + config.tool, config.args, config.testargs, test, cwd, config.runner_quiet + ) + if config.verbose: + sys.stderr.write(f"Running: {' '.join(test_command)}\n") + sys.stderr.flush() + start_time = time.time() + stderr = subprocess.PIPE if not config.verbose else None + process = subprocess.Popen( # nosec + test_command, + stdout=subprocess.PIPE, + stderr=stderr, + universal_newlines=True, + cwd=cwd, + ) + outstr, outerr = process.communicate(timeout=config.timeout) + return_code = process.poll() + duration = time.time() - start_time + if return_code: + raise subprocess.CalledProcessError(return_code, " ".join(test_command)) + + logger.debug('outstr: "%s".', outstr) + out = json.loads(outstr) if outstr else {} + except subprocess.CalledProcessError as err: + if err.returncode == UNSUPPORTED_FEATURE and REQUIRED not in test.get( + "tags", ["required"] + ): + return TestResult( + UNSUPPORTED_FEATURE, outstr, outerr, duration, config.classname + ) + if test.get("should_fail", False): + return TestResult(0, outstr, outerr, duration, config.classname) + if test_number: + logger.error( + """Test %i failed: %s""", + test_number, + " ".join([shlex.quote(tc) for tc in test_command]), + ) + else: + logger.error( + """Test failed: %s""", + " ".join([shlex.quote(tc) for tc in test_command]), + ) + logger.error(test.get("doc", "").replace("\n", " ").strip()) + if err.returncode == UNSUPPORTED_FEATURE: + logger.error("Does not support required feature") + else: + logger.error("Returned non-zero") + return TestResult(1, outstr, outerr, duration, config.classname, str(err)) + except (ruamel.yaml.scanner.ScannerError, TypeError) as err: + logger.error( + """Test %s failed: %s""", + number, + " ".join([shlex.quote(tc) for tc in test_command]), + ) + logger.error(outstr) + logger.error("Parse error %s", str(err)) + logger.error(outerr) + except KeyboardInterrupt: + logger.error( + """Test %s interrupted: %s""", + number, + " ".join([shlex.quote(tc) for tc in test_command]), + ) + raise + except subprocess.TimeoutExpired: + logger.error( + """Test %s timed out: %s""", + number, + " ".join([shlex.quote(tc) for tc in test_command]), + ) + logger.error(test.get("doc", "").replace("\n", " ").strip()) + # Kill and re-communicate to get the logs and reap the child, as + # instructed in the subprocess docs. + if process: + process.kill() + outstr, outerr = process.communicate() + return TestResult( + 2, + outstr, + outerr, + float(cast(int, config.timeout)), + config.classname, + "Test timed out", + ) + finally: + if process is not None and process.returncode is None: + logger.error("""Terminating lingering process""") + process.terminate() + for _ in range(0, 3): + time.sleep(1) + if process.poll() is not None: + break + if process.returncode is None: + process.kill() + + fail_message = "" + + if test.get("should_fail", False): + logger.warning( + """Test %s failed: %s""", + number, + " ".join([shlex.quote(tc) for tc in test_command]), + ) + logger.warning(test.get("doc", "").replace("\n", " ").strip()) + logger.warning("Returned zero but it should be non-zero") + return TestResult(1, outstr, outerr, duration, config.classname) + + try: + compare(test.get("output"), out) + except CompareFail as ex: + logger.warning( + """Test %s failed: %s""", + number, + " ".join([shlex.quote(tc) for tc in test_command]), + ) + logger.warning(test.get("doc", "").replace("\n", " ").strip()) + logger.warning("Compare failure %s", ex) + fail_message = str(ex) + + if config.outdir: + shutil.rmtree(config.outdir, True) + + return TestResult( + (1 if fail_message else 0), + outstr, + outerr, + duration, + config.classname, + fail_message, + ) -def shortname( - name, # type: str -): # type: (...) -> str +def shortname(name: str) -> str: """ Return the short name of a given name. diff --git a/docs/conf.py b/docs/conf.py index 1271b5e..a598182 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -51,7 +51,9 @@ intersphinx_mapping = { "python": ("https://docs.python.org/3", None), "schema_salad": ("https://schema-salad.readthedocs.io/en/stable/", None), - "rdflib": ("https://rdflib.readthedocs.io/en/6.2.0/", None), + #"rdflib": ("https://rdflib.readthedocs.io/en/6.2.0/", None), + #"pytest": ("https://docs.pytest.org/en/7.2.x/", None), + "pytest_xdist": ("https://pytest-xdist.readthedocs.io/en/latest/", None), #"ruamel.yaml": ("https://yaml.readthedocs.io/en/stable/", None), } diff --git a/docs/index.rst b/docs/index.rst index 45c2163..4466152 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,16 +1,20 @@ .. include:: ../README.rst -.. toctree:: - :maxdepth: 2 - +******************** Command Line Options -==================== +******************** .. autoprogram:: cwltest.argparser:arg_parser() :prog: cwltest +.. toctree:: + :maxdepth: 2 + + pytest + +****************** Indices and tables -================== +****************** * :ref:`genindex` * :ref:`modindex` diff --git a/docs/pytest.rst b/docs/pytest.rst new file mode 100644 index 0000000..195d392 --- /dev/null +++ b/docs/pytest.rst @@ -0,0 +1,174 @@ +************* +Pytest plugin +************* + +``cwltest`` can also be used as a Pytest plugin. The CWL test filename must +end with ``.cwltest.yml`` or ``.cwltest.yaml``. + +In this case, the simple command:: + + cwltest --test conformance_xxx.cwltest.yml --tool cwl-runner + +becomes:: + + pytest conformance_xxx.cwltest.yml --cwl-runner cwl-runner + +Command Line Options +==================== + +.. autoprogram:: cwltest.plugin:_doc_options() + :prog: pytest + +Converting ``cwltest`` options to ``pytest`` options +==================================================== + +The table below details all the available command conversions between the two formats. + +.. list-table:: + :widths: 40 30 30 + :header-rows: 1 + + * - Feature + - ``cwltest`` + - ``pytest`` + * - YAML file describing test cases + - ``--test conformance_xxx.cwltest.yml`` + - ``conformance_xxx.cwltest.yml`` + * - CWL runner executable to use + - ``--tool CWL_RUNNER`` + - :option:`--cwl-runner CWL_RUNNER` + * - Specifies the number of tests + + to run simultaneously + - ``-j CORES`` + - ``-n CORES`` [#f1]_ + * - Automatically scale the number of tests + + to run simultaneously + - **UNSUPPORTED** + - ``-n auto`` [#f1]_ + * - Only run one test at a time + + (good for debugging cwltest itself) + - ``-j 1`` + + (or leave out ``-j``) + - ``-n 0 -s`` [#f1]_ + * - Time of execution in seconds + + after which the test will be skipped + - ``--timeout TIMEOUT`` + - ``--timeout TIMEOUT`` [#f3]_ + * - List tests then exit + - ``-l`` + - ``--collect-only`` + * - Run specific tests using their short names + - ``-s TEST_NAME[,TEST_NAME…]`` + - :option:`--cwl-include TEST_NAME[,TEST_NAME…]` + * - Exclude specific tests by short names + - ``-S TEST_NAME[,TEST_NAME…]`` + - :option:`--cwl-exclude TEST_NAME[,TEST_NAME…]` + * - Tags to be tested + - ``--tags TAG[,TAG…]`` + - :option:`--cwl-tags TAG[,TAG…]` + * - Tags not to be tested + - ``--exclude-tags TAG[,TAG…]`` + - :option:`--cwl-exclude-tags TAG[,TAG…]` + * - Path to JUnit xml file + - ``--junit-xml PATH`` + - ``--junit-xml=PATH`` [#f4]_ + * - More verbose output during test run + - ``--verbose`` + - ``-v[vv]`` + * - Additional argument given in test cases + + and required prefix for tool runner + - ``--test-arg ARG_NAME==ARG_PREFIX`` + - :option:`--cwl-test-arg ARG_NAME==ARG_PREFIX` + * - Arguments to pass first to tool runner + - ``cwltest -- ARG [ARG …]`` + - :option:`--cwl-args "ARG [ARG …]"` + * - Only test CommandLineTools + - ``--only-tools`` + - **UNSUPPORTED** + * - Show all tags + - ``--show-tags`` + - **UNSUPPORTED** + * - Store more verbose output to JUnit xml file + - ``--junit-verbose`` + - :option:`--cwl-runner-verbose` [#f4]_ + * - Specify classname for the Test Suite + - ``--classname CLASS_NAME`` + - **UNSUPPORTED** + +.. [#f1] Requires `pytest-xdist `_. + See :ref:`pytest_xdist:parallelization`. +.. [#f2] ``-s`` is a shortcut for ``--capture=no``, also helps with debugging + ``cwltest`` or the cwltest plugin to ``pytest``. +.. [#f3] Requires `pytest-timeout `_. + Note: even if ``pytest-timeout`` is installed, there is no default + timeout. This is different than ``cwltest``'s default timeout of 10 + minutes. + +Differences in the XML output +============================= + +``cwltest --junit-xml`` output + +* top-level ```` element has the elapsed time, and counts (errors, + failures, skipped, and total) +* singular ```` sub-element the same attributes as the top-level + ```` plus ``name`` which is the basename of the YAML test file +* each ```` element has the follow attributes + + * ``name``: the doc string + * ``class``: the tags + * ``file``: the test ID + * ``url``: like "cwltest:conformance_tests#1" + (contains the basename of the YAML test file) + * ``time``: the elapsed time + +* ```` elements always contain the following sub-elements, + regardless of outcome + + * ````: the output object + * ````: stderr (docker pull, other warnings, and errors) + +* ```` elements for failed test cases do not have a ```` sub-element + +``pytest`` with ``cwltest`` plugin XML output + +* top-level ```` element has no attributes +* singular ```` sub-element has the same attributes as the ``cwltest`` + XML version along with these additional attributes + + * ``name``: default is ``pytest`` + (can be customized with the pytest INI option ``junit_suite_name``) + * ``timestamp="2023-01-08T11:39:07.425159"`` + * ``hostname``: the hostname of the machine where the tests ran +* inside the ```` is a ``..`` element + with two ```` elements. But this + `does not work with pytest-xdist `_. + + * ``runner``: the name of the CWL runner + * ``runner_extra_args``: the value of `--cwl-args`` + +* each ```` element has the following attributes + + * ``classname``: always the name of the YAML file (``conformance_test_v1.2.cwltest.yaml``) + * ``name``: the test ID + * ``time``: the elapsed time + +* ```` elements for failed test cases **do** have a ```` sub-element + with a ``message`` attribute containing the :py:meth:`cwltest.plugin.CWLItem.repr_failure` + output. This text is repeated as the content of the ```` element. + The presensce of ```` and ```` sub-elements varies. [#f4]_ + + .. [#f4] Depending on the value of the pytest INI option ``junit_logging``, + then ```` and ```` sub-elements will be generated. + However the default value for ``junit_logging`` is ``no``, so to get + either of these pick one from `the full list + `_. + You can set ``junit_logging`` in `a configuration file + `_ + or on the command line: ``pytest -o junit_logging=out-err``. diff --git a/gittaggers.py b/gittaggers.py index e91cf0f..39e79f7 100644 --- a/gittaggers.py +++ b/gittaggers.py @@ -1,5 +1,6 @@ import subprocess import time + import pkg_resources from setuptools.command.egg_info import egg_info diff --git a/mypy-requirements.txt b/mypy-requirements.txt index f620fb9..381abed 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,3 +1,5 @@ mypy==0.991 types-setuptools types-requests +types-PyYAML +cwltool diff --git a/mypy-stubs/defusedxml/__init__.py b/mypy-stubs/defusedxml/__init__.pyi similarity index 100% rename from mypy-stubs/defusedxml/__init__.py rename to mypy-stubs/defusedxml/__init__.pyi diff --git a/mypy-stubs/ruamel/__init__.py b/mypy-stubs/ruamel/__init__.pyi similarity index 100% rename from mypy-stubs/ruamel/__init__.py rename to mypy-stubs/ruamel/__init__.pyi diff --git a/release-test.sh b/release-test.sh index 42684e0..d7010b0 100755 --- a/release-test.sh +++ b/release-test.sh @@ -17,7 +17,7 @@ else repo=https://github.com/common-workflow-language/cwltest.git HEAD=$(git rev-parse HEAD) fi -run_tests="bin/py.test --pyargs ${module}" +run_tests="bin/py.test -p pytester --pyargs ${module}" pipver=20.3.3 # minimum required version of pip for Python 3.10 setuptoolsver=50.0.1 # required for Python 3.10 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" diff --git a/requirements.txt b/requirements.txt index a51fd20..a15d1b3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ schema-salad >= 5.0.20200220195218, < 9 junit-xml >= 1.8 -pytest < 8 +pytest >= 7, < 8 defusedxml +typing-extensions diff --git a/setup.py b/setup.py index e2b1528..2a32a17 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,11 @@ #!/usr/bin/env python3 import os +import pathlib import sys import setuptools.command.egg_info as egg_info_cmd from setuptools import setup -import cwltest - SETUP_DIR = os.path.dirname(__file__) README = os.path.join(SETUP_DIR, "README.rst") @@ -17,12 +16,6 @@ except ImportError: tagger = egg_info_cmd.egg_info -install_requires = [ - "schema-salad >= 5.0.20200220195218, < 9", - "junit-xml >= 1.8", - "defusedxml", -] - needs_pytest = {"pytest", "test", "ptr"}.intersection(sys.argv) pytest_runner = ["pytest < 8", "pytest-runner"] if needs_pytest else [] @@ -43,13 +36,25 @@ package_dir={"cwltest.tests": "tests"}, package_data={"cwltest": ["py.typed"], "tests": ["test-data/*"]}, include_package_data=True, - install_requires=install_requires, + install_requires=open( + os.path.join(pathlib.Path(__file__).parent, "requirements.txt") + ) + .read() + .splitlines(), test_suite="tests", - tests_require=["pytest<8"], + tests_require=open( + os.path.join(pathlib.Path(__file__).parent, "test-requirements.txt") + ) + .read() + .splitlines(), + extras_require={"pytest-plugin": ["pytest"]}, entry_points={ "console_scripts": [ "cwltest=cwltest.main:main", - ] + ], + "pytest11": [ + "cwl = cwltest.plugin [pytest-plugin]", + ], }, zip_safe=True, cmdclass={"egg_info": tagger}, diff --git a/test-requirements.txt b/test-requirements.txt index e5540ed..6f0a196 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,2 +1,5 @@ -pytest >= 6.2, < 7.3 +cwlref-runner +cwltool +pytest >= 7, < 8 pytest-cov +pytest-xdist diff --git a/tests/test-data/conformance_test_v1.0.cwltest.yml b/tests/test-data/conformance_test_v1.0.cwltest.yml new file mode 100644 index 0000000..75f7086 --- /dev/null +++ b/tests/test-data/conformance_test_v1.0.cwltest.yml @@ -0,0 +1,17 @@ +- output: + args: [cat, hello.txt] + job: v1.0/cat-job.json + tool: v1.0/cat1-testcli.cwl + label: cl_optional_inputs_missing + id: 4 + doc: Test command line with optional input (missing) + tags: [ required, command_line_tool ] + +- output: + args: [cat, -n, hello.txt] + job: v1.0/cat-n-job.json + tool: v1.0/cat1-testcli.cwl + label: cl_optional_bindings_provided + id: 5 + doc: Test command line with optional input (provided) + tags: [ command_line_tool ] \ No newline at end of file diff --git a/tests/test-data/conformance_test_v1.2.cwltest.yaml b/tests/test-data/conformance_test_v1.2.cwltest.yaml new file mode 100644 index 0000000..0b78da9 --- /dev/null +++ b/tests/test-data/conformance_test_v1.2.cwltest.yaml @@ -0,0 +1,15 @@ +- output: + args: [cat, hello.txt] + job: v1.0/cat-job.json + tool: v1.0/cat1-testcli.cwl + id: cl_optional_inputs_missing + doc: Test command line with optional input (missing) + tags: [ required, command_line_tool ] + +- output: + args: [cat, -n, hello.txt] + job: v1.0/cat-n-job.json + tool: v1.0/cat1-testcli.cwl + id: cl_optional_bindings_provided + doc: Test command line with optional input (provided) + tags: [ command_line_tool ] \ No newline at end of file diff --git a/tests/test-data/cwltool-conftest.py b/tests/test-data/cwltool-conftest.py new file mode 100644 index 0000000..061b994 --- /dev/null +++ b/tests/test-data/cwltool-conftest.py @@ -0,0 +1,37 @@ +""" +Example configuration for pytest-cwl plugin using cwltool directly. + +Calls cwltool via Python, instead of a subprocess via `--cwl-runner cwltool`. +""" +import json +from io import StringIO +from typing import Any, Dict, List, Optional, Tuple + +from cwltest import utils + + +def pytest_cwl_execute_test( + config: utils.CWLTestConfig, + processfile: str, + jobfile: Optional[str] +) -> Tuple[int, Optional[Dict[str, Any]]]: + """Use the CWL reference runner (cwltool) to execute tests.""" + from cwltool import main + from cwltool.errors import WorkflowException + + stdout = StringIO() + argsl: List[str] = [f"--outdir={config.outdir}"] + if config.runner_quiet: + argsl.append("--quiet") + elif config.verbose: + argsl.append("--debug") + argsl.extend(config.args) + argsl.append(processfile) + if jobfile: + argsl.append(jobfile) + try: + result = main.main(argsl=argsl, stdout=stdout) + except WorkflowException: + return 1, {} + out = stdout.getvalue() + return result, json.loads(out) if out else {} diff --git a/tests/test-data/v1.0/args.py b/tests/test-data/v1.0/args.py new file mode 100644 index 0000000..190fd5c --- /dev/null +++ b/tests/test-data/v1.0/args.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python +import sys +import json +import os +args = [os.path.basename(a) for a in sys.argv[1:]] +with open("cwl.output.json", "w") as f: + json.dump({"args": args}, f) \ No newline at end of file diff --git a/tests/test-data/v1.0/cat-job.json b/tests/test-data/v1.0/cat-job.json index e69de29..b4b3b6b 100644 --- a/tests/test-data/v1.0/cat-job.json +++ b/tests/test-data/v1.0/cat-job.json @@ -0,0 +1,6 @@ +{ + "file1": { + "class": "File", + "location": "hello.txt" + } +} \ No newline at end of file diff --git a/tests/test-data/v1.0/cat-n-job.json b/tests/test-data/v1.0/cat-n-job.json new file mode 100644 index 0000000..77e3537 --- /dev/null +++ b/tests/test-data/v1.0/cat-n-job.json @@ -0,0 +1,7 @@ +{ + "file1": { + "class": "File", + "location": "hello.txt" + }, + "numbering": true +} \ No newline at end of file diff --git a/tests/test-data/v1.0/cat1-testcli.cwl b/tests/test-data/v1.0/cat1-testcli.cwl new file mode 100644 index 0000000..311cd86 --- /dev/null +++ b/tests/test-data/v1.0/cat1-testcli.cwl @@ -0,0 +1,45 @@ +#!/usr/bin/env cwl-runner +{ + "class": "CommandLineTool", + "cwlVersion": "v1.0", + "doc": "Print the contents of a file to stdout using 'cat' running in a docker container.", + "hints": [ + { + "class": "DockerRequirement", + "dockerPull": "python:2-slim" + }, + { + "class": "ResourceRequirement", + "ramMin": 128 + } + ], + "inputs": [ + { + "id": "file1", + "type": "File", + "inputBinding": {"position": 1} + }, + { + "id": "numbering", + "type": ["null", "boolean"], + "inputBinding": { + "position": 0, + "prefix": "-n" + } + }, + { + id: "args.py", + type: File, + default: { + class: File, + location: args.py + }, + inputBinding: { + position: -1 + } + } + ], + "outputs": [{"id": "args", "type": "string[]"}], + "baseCommand": "python", + "arguments": ["cat"] +} \ No newline at end of file diff --git a/tests/test-data/v1.0/hello.txt b/tests/test-data/v1.0/hello.txt new file mode 100644 index 0000000..6769dd6 --- /dev/null +++ b/tests/test-data/v1.0/hello.txt @@ -0,0 +1 @@ +Hello world! \ No newline at end of file diff --git a/tests/test_categories.py b/tests/test_categories.py index 28acb90..c6461e9 100644 --- a/tests/test_categories.py +++ b/tests/test_categories.py @@ -1,15 +1,16 @@ -import re import os +import re from os import linesep as n from os import sep as p from pathlib import Path from typing import cast from xml.etree.ElementTree import Element -from .util import run_with_mock_cwl_runner, get_data import defusedxml.ElementTree as ET import schema_salad.ref_resolver +from .util import get_data, run_with_mock_cwl_runner + def test_unsupported_with_required_tests() -> None: cwl_runner = get_data("tests/test-data/mock_cwl_runner.py") @@ -41,13 +42,11 @@ def test_unsupported_with_required_tests() -> None: "Test 1 failed: {cwl_runner} --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" "Required test that is unsupported (without tags){n}" "Does not support required feature{n}" - "{n}" "Test [2/2] Required test that is unsupported (with tags){n}" "{n}" "Test 2 failed: {cwl_runner} --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" "Required test that is unsupported (with tags){n}" "Does not support required feature{n}" - "{n}" "0 tests passed, 2 failures, 0 unsupported features{n}".format( cwl_runner=cwl_runner, n=n, p=p, q=q ) @@ -62,6 +61,7 @@ def test_unsupported_with_optional_tests() -> None: ), ] error_code, stdout, stderr = run_with_mock_cwl_runner(args) + stderr = re.sub(r" '?--outdir=[^ ]*", "", stderr) assert error_code == 0 assert ( "The `id` field is missing.{n}" diff --git a/tests/test_compare.py b/tests/test_compare.py index aec983e..86d456e 100644 --- a/tests/test_compare.py +++ b/tests/test_compare.py @@ -1,26 +1,34 @@ -from .util import get_data -from cwltest.utils import CompareFail, compare_file, compare +from typing import Any, Dict import pytest +from cwltest.compare import CompareFail, compare + +from .util import get_data + + +def test_compare_any_success() -> None: + expected = "Any" + actual: Dict[str, Any] = {} + compare(expected, actual) -def test_compare_file() -> None: +def test_compare_contents_failure() -> None: expected = { "location": "cores.txt", "size": 2, "class": "File", - "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", + "contents": "2", } - actual = { "basename": "cores.txt", "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", "class": "File", "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", - "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", + "path": get_data("tests/test-data/cores.txt"), "size": 2, } - compare_file(expected, actual) + with pytest.raises(CompareFail): + compare(expected, actual) def test_compare_contents_success() -> None: @@ -30,7 +38,6 @@ def test_compare_contents_success() -> None: "class": "File", "contents": "2\n", } - actual = { "basename": "cores.txt", "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", @@ -42,21 +49,403 @@ def test_compare_contents_success() -> None: compare(expected, actual) -def test_compare_contents_failure() -> None: +def test_compare_directory_success() -> None: + expected = { + "stuff": { + "class": "Directory", + "listing": [ + { + "basename": "baz.txt", + "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709", + "class": "File", + "size": 0, + }, + { + "basename": "foo", + "class": "Directory", + "listing": [ + { + "basename": "bar.txt", + "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709", + "class": "File", + "size": 0, + } + ], + }, + ], + } + } + actual = { + "stuff": { + "class": "Directory", + "listing": [ + { + "basename": "baz.txt", + "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709", + "class": "File", + "size": 0, + }, + { + "basename": "foo", + "class": "Directory", + "listing": [ + { + "basename": "bar.txt", + "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709", + "class": "File", + "size": 0, + } + ], + }, + ], + } + } + compare(expected, actual) + + +def test_compare_directory_failure_different_listing() -> None: + expected = { + "stuff": { + "class": "Directory", + "listing": [ + { + "basename": "baz.txt", + "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709", + "class": "File", + "size": 0, + }, + { + "basename": "foo", + "class": "Directory", + "listing": [ + { + "basename": "bar.txt", + "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709", + "class": "File", + "size": 0, + } + ], + }, + ], + } + } + actual = { + "stuff": { + "class": "Directory", + "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff", + "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff", + "listing": [ + { + "basename": "baz.txt", + "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709", + "class": "File", + "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/baz.txt", + "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/baz.txt", + "size": 0, + }, + { + "basename": "foo", + "class": "Directory", + "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/foo", + "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/foo", + "listing": [ + { + "basename": "bar.txt", + "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80775", + "class": "File", + "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/foo/bar.txt", + "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/foo/bar.txt", + "size": 0, + } + ], + }, + ], + } + } + with pytest.raises(CompareFail): + compare(expected, actual) + + +def test_compare_directory_failure_no_listing() -> None: + expected = { + "stuff": { + "class": "Directory", + "listing": [ + { + "basename": "baz.txt", + "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709", + "class": "File", + "size": 0, + }, + { + "basename": "foo", + "class": "Directory", + "listing": [ + { + "basename": "bar.txt", + "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709", + "class": "File", + "size": 0, + } + ], + }, + ], + } + } + actual = { + "stuff": { + "class": "Directory", + "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff", + "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff", + "listing": [ + { + "basename": "baz.txt", + "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709", + "class": "File", + "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/baz.txt", + "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/baz.txt", + "size": 0, + }, + { + "basename": "foo", + "class": "Directory", + "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/foo", + "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/foo", + }, + ], + } + } + with pytest.raises(CompareFail): + compare(expected, actual) + + +def test_compare_file_failure_different() -> None: expected = { "location": "cores.txt", "size": 2, "class": "File", - "contents": "2", + "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7b", + } + actual = { + "basename": "cores.txt", + "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", + "class": "File", + "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", + "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", + "size": 2, } + with pytest.raises(CompareFail): + compare(expected, actual) + + +def test_compare_file_failure_none() -> None: + expected = { + "location": "cores.txt", + "size": 2, + "class": "File", + "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7b", + } + actual: Dict[str, Any] = {} + with pytest.raises(CompareFail): + compare(expected, actual) + +def test_compare_file_success() -> None: + expected = { + "location": "cores.txt", + "size": 2, + "class": "File", + "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", + } actual = { "basename": "cores.txt", "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", "class": "File", "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", - "path": get_data("tests/test-data/cores.txt"), + "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", "size": 2, } + compare(expected, actual) + + +def test_compare_list_failure_missing() -> None: + expected = { + "args": [ + "tmap", + "mapall", + "stage1", + "map1", + "--min-seq-length", + "20", + "map2", + "--min-seq-length", + "20", + "stage2", + "map1", + "--max-seq-length", + "20", + "--min-seq-length", + "10", + "--seed-length", + "16", + "map2", + "--max-seed-hits", + "-1", + "--max-seq-length", + "20", + "--min-seq-length", + "10", + ] + } + actual = { + "args": [ + "tmap", + "mapall", + "stage1", + "map1", + "stage2", + "map1", + "--max-seq-length", + "20", + "--min-seq-length", + "10", + "--seed-length", + "16", + "map2", + "--max-seed-hits", + "-1", + "--max-seq-length", + "20", + "--min-seq-length", + "10", + ] + } with pytest.raises(CompareFail): - compare_file(expected, actual) + compare(expected, actual) + + +def test_compare_list_failure_order() -> None: + expected = { + "args": [ + "tmap", + "mapall", + "stage1", + "map1", + "--min-seq-length", + "20", + "map2", + "--min-seq-length", + "20", + "stage2", + "map1", + "--max-seq-length", + "20", + "--min-seq-length", + "10", + "--seed-length", + "16", + "map2", + "--max-seed-hits", + "-1", + "--max-seq-length", + "20", + "--min-seq-length", + "10", + ] + } + actual = { + "args": [ + "tmap", + "mapall", + "stage1", + "map1", + "--min-seq-length", + "20", + "map2", + "--min-seq-length", + "20", + "stage2", + "map2", + "--max-seed-hits", + "-1", + "--max-seq-length", + "20", + "--min-seq-length", + "10", + "map1", + "--max-seq-length", + "20", + "--min-seq-length", + "10", + "--seed-length", + "16", + ] + } + with pytest.raises(CompareFail): + compare(expected, actual) + + +def test_compare_list_failure_type() -> None: + expected = { + "args": [ + "tmap", + "mapall", + "stage1", + "map1", + "--min-seq-length", + "20", + "map2", + "--min-seq-length", + "20", + "stage2", + "map1", + "--max-seq-length", + "20", + "--min-seq-length", + "10", + "--seed-length", + "16", + "map2", + "--max-seed-hits", + "-1", + "--max-seq-length", + "20", + "--min-seq-length", + "10", + ] + } + actual: Dict[str, Any] = {"args": {}} + with pytest.raises(CompareFail): + compare(expected, actual) + + +def test_compare_list_success() -> None: + expected = { + "args": [ + "tmap", + "mapall", + "stage1", + "map1", + "--min-seq-length", + "20", + "map2", + "--min-seq-length", + "20", + "stage2", + "map1", + "--max-seq-length", + "20", + "--min-seq-length", + "10", + "--seed-length", + "16", + "map2", + "--max-seed-hits", + "-1", + "--max-seq-length", + "20", + "--min-seq-length", + "10", + ] + } + compare(expected, expected) diff --git a/tests/test_plugin.py b/tests/test_plugin.py new file mode 100644 index 0000000..4951c3f --- /dev/null +++ b/tests/test_plugin.py @@ -0,0 +1,126 @@ +import os +import shutil +from pathlib import Path +from typing import TYPE_CHECKING + +from .util import get_data + +if TYPE_CHECKING: + from _pytest.pytester import Pytester + + +def _load_v1_0_dir(path: Path) -> None: + inner_dir = os.path.join(path.parent, "v1.0") + os.mkdir(inner_dir) + shutil.copy(get_data("tests/test-data/v1.0/cat1-testcli.cwl"), inner_dir) + shutil.copy(get_data("tests/test-data/v1.0/cat-job.json"), inner_dir) + shutil.copy(get_data("tests/test-data/v1.0/cat-n-job.json"), inner_dir) + shutil.copy(get_data("tests/test-data/v1.0/hello.txt"), inner_dir) + shutil.copy(get_data("tests/test-data/v1.0/args.py"), inner_dir) + + +def test_include(pytester: "Pytester") -> None: + """Test the pytest plugin using cwltool as cwl-runner.""" + path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") + shutil.copy( + get_data("tests/test-data/cwltool-conftest.py"), path.parent / "conftest.py" + ) + _load_v1_0_dir(path) + result = pytester.runpytest( + "-k", + "conformance_test_v1.0.cwltest.yml", + "--cwl-include", + "cl_optional_inputs_missing", + ) + result.assert_outcomes(passed=1, skipped=1) + + +def test_exclude(pytester: "Pytester") -> None: + """Test the pytest plugin using cwltool as cwl-runner.""" + path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") + shutil.copy( + get_data("tests/test-data/cwltool-conftest.py"), path.parent / "conftest.py" + ) + _load_v1_0_dir(path) + result = pytester.runpytest( + "-k", + "conformance_test_v1.0.cwltest.yml", + "--cwl-exclude", + "cl_optional_inputs_missing,cl_optional_bindings_provided", + ) + result.assert_outcomes(passed=0, skipped=2) + + +def test_tags(pytester: "Pytester") -> None: + """Test the pytest plugin using cwltool as cwl-runner.""" + path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") + shutil.copy( + get_data("tests/test-data/cwltool-conftest.py"), path.parent / "conftest.py" + ) + _load_v1_0_dir(path) + result = pytester.runpytest( + "-k", "conformance_test_v1.0.cwltest.yml", "--cwl-tags", "required" + ) + result.assert_outcomes(passed=1, skipped=1) + + +def test_exclude_tags(pytester: "Pytester") -> None: + """Test the pytest plugin using cwltool as cwl-runner.""" + path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") + shutil.copy( + get_data("tests/test-data/cwltool-conftest.py"), path.parent / "conftest.py" + ) + _load_v1_0_dir(path) + result = pytester.runpytest( + "-k", + "conformance_test_v1.0.cwltest.yml", + "--cwl-exclude-tags", + "command_line_tool", + ) + result.assert_outcomes(skipped=2) + + +def test_badgedir(pytester: "Pytester") -> None: + """Test the pytest plugin creates the badges directory.""" + path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") + shutil.copy( + get_data("tests/test-data/cwltool-conftest.py"), path.parent / "conftest.py" + ) + _load_v1_0_dir(path) + assert not os.path.exists("cwl-badges") + pytester.runpytest( + "-k", "conformance_test_v1.0.cwltest.yml", "--cwl-badgedir", "cwl-badges" + ) + assert os.path.exists("cwl-badges") + + +def test_no_label(pytester: "Pytester") -> None: + """Test the pytest plugin correctly extracts test names from the id field when label is missing.""" + path = pytester.copy_example("conformance_test_v1.2.cwltest.yaml") + shutil.copy( + get_data("tests/test-data/cwltool-conftest.py"), path.parent / "conftest.py" + ) + _load_v1_0_dir(path) + result = pytester.runpytest( + "-k", "conformance_test_v1.2.cwltest.yaml", "--cwl-tags", "required" + ) + result.assert_outcomes(passed=1, skipped=1) + + +def test_cwltool_hook(pytester: "Pytester") -> None: + """Test the pytest plugin using cwltool as cwl-runner.""" + path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") + shutil.copy( + get_data("tests/test-data/cwltool-conftest.py"), path.parent / "conftest.py" + ) + _load_v1_0_dir(path) + result = pytester.runpytest("-k", "conformance_test_v1.0.cwltest.yml") + result.assert_outcomes(passed=2) + + +def test_no_hook(pytester: "Pytester") -> None: + """Test the pytest plugin using the default cwl-runner.""" + path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") + _load_v1_0_dir(path) + result = pytester.runpytest("-k", "conformance_test_v1.0.cwltest.yml") + result.assert_outcomes(passed=2) diff --git a/tests/util.py b/tests/util.py index 145d0b2..002fa53 100644 --- a/tests/util.py +++ b/tests/util.py @@ -2,11 +2,7 @@ import subprocess # nosec from typing import List, Tuple -from pkg_resources import ( - Requirement, - ResolutionError, - resource_filename, -) +from pkg_resources import Requirement, ResolutionError, resource_filename def get_data(filename: str) -> str: diff --git a/tox.ini b/tox.ini index 5e47e6a..b0b4234 100644 --- a/tox.ini +++ b/tox.ini @@ -10,6 +10,8 @@ envlist = skip_missing_interpreters = True [pytest] +addopts = -p pytester -n auto +pytester_example_dir = tests/test-data testpaths = tests [gh-actions] @@ -22,6 +24,9 @@ python = 3.11: py311 [testenv] +skipsdist = + py3{6,7,8,9,10,11}-!{unit,mypy,lintreadme} = True + description = py{36,37,38,39,310,311}-unit: Run the unit tests py{36,37,38,39,310,311}-lint: Lint the Python code @@ -44,10 +49,15 @@ deps = setenv = py{36,37,38,39,310,311}-unit: LC_ALL = C.UTF-8 + COV_CORE_SOURCE=cwltest + COV_CORE_CONFIG={toxinidir}/.coveragerc + COV_CORE_DATAFILE={toxinidir}/.coverage.eager + commands = py{36,37,38,39,310,311}-unit: python -m pip install -U pip setuptools wheel - py{36,37,38,39,310,311}-unit: make coverage-report coverage.xml PYTEST_EXTRA={posargs} + py{36,37,38,39,310,311}-unit: python -m pytest --cov --cov-config={toxinidir}/.coveragerc --cov-append {posargs} + py{36,37,38,39,310,311}-unit: coverage xml py{36,37,38,39,310,311}-bandit: bandit --recursive cwltest --exclude tests/* py{36,37,38,39,310,311}-lint: make flake8 py{36,37,38,39,310,311}-lint: make format-check @@ -75,11 +85,10 @@ skip_install = true [testenv:py310-lintreadme] description = Lint the README.rst->.md conversion commands = - python setup.py sdist - python setup.py bdist_wheel - twine check dist/* + python -m build --outdir {distdir} + twine check {distdir}/* deps = twine - wheel - readme_renderer[md] + build + readme_renderer[rst] skip_install = true From de7f1ad0e67893dea622856dfc5c74b3d9d92f41 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" <1330696+mr-c@users.noreply.github.com> Date: Sun, 8 Jan 2023 20:36:15 +0100 Subject: [PATCH 056/165] Prepare for the release of 2.3.x --- Makefile | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 2c7d049..ced0a68 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ PYSOURCES=$(wildcard ${MODULE}/**.py tests/*.py) setup.py DEVPKGS=-rdev-requirements.txt -rtest-requirements.txt -rmypy-requirements.txt DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage pydocstyle sloccount \ python-flake8 python-mock shellcheck -VERSION=2.2.$(shell TZ=UTC git log --first-parent --max-count=1 \ +VERSION=2.3.$(shell TZ=UTC git log --first-parent --max-count=1 \ --format=format:%cd --date=format-local:%Y%m%d%H%M%S) ## all : default task (install in dev mode) diff --git a/setup.py b/setup.py index 2a32a17..5b9c52f 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ setup( name="cwltest", - version="2.2", # update the VERSION prefix in the Makefile as well 🙂 + version="2.3", # update the VERSION prefix in the Makefile as well 🙂 description="Common Workflow Language testing framework", long_description=open(README).read(), long_description_content_type="text/x-rst", From 7152c432b110f2c64905aac8eed09330dfa05f97 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" <1330696+mr-c@users.noreply.github.com> Date: Mon, 9 Jan 2023 10:35:31 +0100 Subject: [PATCH 057/165] CodeQL: limit scans --- .github/workflows/codeql-analysis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7993d84..292544f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -2,7 +2,9 @@ name: "Code scanning - action" on: push: + branches: [main] pull_request: + branches: [main] schedule: - cron: '0 17 * * 0' From 657872b89308b0bb05e1abfa7cc30d5572b1905e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Jan 2023 10:42:01 +0100 Subject: [PATCH 058/165] Update tox requirement from <4 to <5 (#159) Updates the requirements on [tox](https://github.com/tox-dev/tox) to permit the latest version. - [Release notes](https://github.com/tox-dev/tox/releases) - [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst) - [Commits](https://github.com/tox-dev/tox/compare/0.5...4.2.6) --- updated-dependencies: - dependency-name: tox dependency-type: direct:development ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index 3b58070..5af12b2 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -4,7 +4,7 @@ pylint pep257 pydocstyle flake8 -tox < 4 +tox < 5 tox-pyenv isort wheel From 7061207c818d2c77bac86305c70dcf60ed56b58d Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" <1330696+mr-c@users.noreply.github.com> Date: Mon, 30 Jan 2023 15:23:16 +0100 Subject: [PATCH 059/165] use CODECOV_TOKEN to avoid CI fails (#160) --- .github/workflows/ci-tests.yml | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 3738b7b..ddd8e49 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -39,12 +39,11 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ env.py-semver }} - - - name: Cache for pip - uses: actions/cache@v3 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ matrix.step }}-${{ hashFiles('requirements.txt', 'tox.ini') }} + cache: pip + cache-dependency-path: | + requirements.txt + test-requirements.txt + mypy-requirements.txt - name: Upgrade setuptools and install tox run: | @@ -66,6 +65,7 @@ jobs: uses: codecov/codecov-action@v3 with: fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} tox-style: name: CI linters via Tox @@ -89,12 +89,11 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ env.py-semver }} - - - name: Cache for pip - uses: actions/cache@v3 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ matrix.step }}-${{ hashFiles('requirements.txt') }} + cache: pip + cache-dependency-path: | + requirements.txt + test-requirements.txt + mypy-requirements.txt - name: Upgrade setuptools and install tox run: | @@ -120,12 +119,11 @@ jobs: uses: actions/setup-python@v4 with: python-version: "3.10" # quoted, otherwise that turns into the number 3.1 - - - name: Cache for pip - uses: actions/cache@v3 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-release-${{ hashFiles('requirements.txt', 'test-requirements.txt') }} + cache: pip + cache-dependency-path: | + requirements.txt + test-requirements.txt + mypy-requirements.txt - name: Install packages run: | From d3532f3487d921726fae26c7815488b1b99b95f0 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" <1330696+mr-c@users.noreply.github.com> Date: Tue, 31 Jan 2023 11:51:15 +0100 Subject: [PATCH 060/165] readthedocs: install graphviz (#161) --- .readthedocs.yml | 2 ++ docs/index.rst | 1 + 2 files changed, 3 insertions(+) diff --git a/.readthedocs.yml b/.readthedocs.yml index 5a74019..cd1f440 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -16,6 +16,8 @@ build: os: ubuntu-22.04 tools: python: "3.11" + apt_packages: + - graphviz python: install: diff --git a/docs/index.rst b/docs/index.rst index 4466152..ce7ab8a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -11,6 +11,7 @@ Command Line Options :maxdepth: 2 pytest + autoapi/index ****************** Indices and tables From 3a290cb8ddb764e78cdaa22f555b906ec1068355 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Feb 2023 00:02:19 +0000 Subject: [PATCH 061/165] Bump mypy from 0.991 to 1.0.0 Bumps [mypy](https://github.com/python/mypy) from 0.991 to 1.0.0. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.991...v1.0.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 381abed..671641f 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==0.991 +mypy==1.0.0 types-setuptools types-requests types-PyYAML From 343562963673af2b239f773c89ede956482d6c2f Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Mon, 13 Feb 2023 18:05:17 +0100 Subject: [PATCH 062/165] upgrade black & format --- cwltest/compare.py | 29 +++++++++++++---------------- cwltest/main.py | 2 +- cwltest/plugin.py | 4 ++-- cwltest/utils.py | 11 ++++++++--- dev-requirements.txt | 2 +- tox.ini | 2 +- 6 files changed, 26 insertions(+), 24 deletions(-) diff --git a/cwltest/compare.py b/cwltest/compare.py index b56a7c3..2278a86 100644 --- a/cwltest/compare.py +++ b/cwltest/compare.py @@ -1,15 +1,16 @@ """Compare utilities for CWL objects.""" import json -from typing import Any, Dict, Set +from typing import Any, Dict, Optional, Set class CompareFail(Exception): """Compared CWL objects are not equal.""" @classmethod - def format(cls, expected, actual, cause=None): - # type: (Any, Any, Any) -> CompareFail + def format( + cls, expected: Any, actual: Any, cause: Optional[Any] = None + ) -> "CompareFail": """Load the difference details into the error message.""" message = "expected: {}\ngot: {}".format( json.dumps(expected, indent=4, sort_keys=True), @@ -20,8 +21,9 @@ def format(cls, expected, actual, cause=None): return cls(message) -def _check_keys(keys, expected, actual): - # type: (Set[str], Dict[str,Any], Dict[str,Any]) -> None +def _check_keys( + keys: Set[str], expected: Dict[str, Any], actual: Dict[str, Any] +) -> None: for k in keys: try: compare(expected.get(k), actual.get(k)) @@ -31,8 +33,7 @@ def _check_keys(keys, expected, actual): ) from e -def _compare_contents(expected, actual): - # type: (Dict[str,Any], Dict[str,Any]) -> None +def _compare_contents(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: expected_contents = expected["contents"] with open(actual["path"]) as f: actual_contents = f.read() @@ -47,8 +48,7 @@ def _compare_contents(expected, actual): ) -def _compare_dict(expected, actual): - # type: (Dict[str,Any], Dict[str,Any]) -> None +def _compare_dict(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: for c in expected: try: compare(expected[c], actual.get(c)) @@ -62,8 +62,7 @@ def _compare_dict(expected, actual): raise CompareFail.format(expected, actual, "unexpected key '%s'" % k) -def _compare_directory(expected, actual): - # type: (Dict[str,Any], Dict[str,Any]) -> None +def _compare_directory(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: if actual.get("class") != "Directory": raise CompareFail.format( expected, actual, "expected object with a class 'Directory'" @@ -90,8 +89,7 @@ def _compare_directory(expected, actual): _compare_file(expected, actual) -def _compare_file(expected, actual): - # type: (Dict[str,Any], Dict[str,Any]) -> None +def _compare_file(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: _compare_location(expected, actual) if "contents" in expected: _compare_contents(expected, actual) @@ -100,8 +98,7 @@ def _compare_file(expected, actual): _check_keys(other_keys, expected, actual) -def _compare_location(expected, actual): - # type: (Dict[str,Any], Dict[str,Any]) -> None +def _compare_location(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: if "path" in expected: comp = "path" if "path" not in actual: @@ -126,7 +123,7 @@ def _compare_location(expected, actual): ) -def compare(expected, actual): # type: (Any, Any) -> None +def compare(expected: Any, actual: Any) -> None: """Compare two CWL objects.""" if expected == "Any": return diff --git a/cwltest/main.py b/cwltest/main.py index 6c9d293..f93a279 100644 --- a/cwltest/main.py +++ b/cwltest/main.py @@ -144,7 +144,7 @@ def main() -> int: logger.warning("The `id` field is missing.") if args.show_tags: - alltags = set() # type: Set[str] + alltags: Set[str] = set() for t in tests: ts = t.get("tags", []) alltags |= set(ts) diff --git a/cwltest/plugin.py b/cwltest/plugin.py index c642519..d59c2f5 100644 --- a/cwltest/plugin.py +++ b/cwltest/plugin.py @@ -7,23 +7,23 @@ from io import StringIO from pathlib import Path from typing import ( + TYPE_CHECKING, Any, Dict, Iterator, List, Optional, Set, - TYPE_CHECKING, Tuple, Union, cast, ) import pytest +from cwltest.compare import CompareFail, compare from typing_extensions import Protocol from cwltest import REQUIRED, UNSUPPORTED_FEATURE, logger, utils -from cwltest.compare import CompareFail, compare if TYPE_CHECKING: from _pytest._code.code import ExceptionInfo, _TracebackStyle diff --git a/cwltest/utils.py b/cwltest/utils.py index 036fafb..d47f376 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -35,7 +35,7 @@ from cwltest import REQUIRED, UNSUPPORTED_FEATURE, logger, templock -class CWLTestConfig(object): +class CWLTestConfig: """Store configuration values for cwltest.""" def __init__( @@ -173,14 +173,19 @@ def load_and_validate_tests(path: str) -> Tuple[Any, Dict[str, Any]]: "utf-8" ) } - (document_loader, avsc_names, _, _,) = schema_salad.schema.load_schema( + ( + document_loader, + avsc_names, + _, + _, + ) = schema_salad.schema.load_schema( "https://w3id.org/cwl/cwltest/cwltest-schema.yml", cache=cache ) if not isinstance(avsc_names, schema_salad.avro.schema.Names): print(avsc_names) raise ValidationException( - "Wrong instance for avsc_names: {}".format(type(avsc_names)) + f"Wrong instance for avsc_names: {type(avsc_names)}" ) tests, metadata = schema_salad.schema.load_and_validate( diff --git a/dev-requirements.txt b/dev-requirements.txt index 5af12b2..4ac7321 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ diff_cover -black +black ~= 23.1 pylint pep257 pydocstyle diff --git a/tox.ini b/tox.ini index b0b4234..0ac4e44 100644 --- a/tox.ini +++ b/tox.ini @@ -43,7 +43,7 @@ deps = py{36,37,38,39,310,311}-{unit,mypy}: -rrequirements.txt py{36,37,38,39,310,311}-{unit,mypy}: -rtest-requirements.txt py{36,37,38,39,310,311}-lint: flake8-bugbear - py{36,37,38,39,310,311}-lint: black + py{36,37,38,39,310,311}-lint: black~=23.1 py{36,37,38,39,310,311}-bandit: bandit py{37,38,39,310,311}-mypy: -rmypy-requirements.txt From f0bae2d3ca894fb09f4856ba9a66892fd82b4244 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Mon, 13 Feb 2023 18:16:44 +0100 Subject: [PATCH 063/165] flake8 config upgrade --- .flake8 | 9 ++++++--- cwltest/compare.py | 4 ++-- cwltest/plugin.py | 8 ++++---- cwltest/utils.py | 6 ++---- setup.cfg | 5 ----- tests/test_compare.py | 15 ++++++++++----- 6 files changed, 24 insertions(+), 23 deletions(-) diff --git a/.flake8 b/.flake8 index 35967ff..ed7277f 100644 --- a/.flake8 +++ b/.flake8 @@ -1,4 +1,7 @@ [flake8] -ignore = E203, E266, E501, W503, E211, E731 -max-line-length = 88 -select = B,C,E,F,W,T4,B9 +ignore = E203,W503 +max-line-length = 100 +select = B,C,E,F,W,T4 +extend-ignore = E501,B905 +# when Python 3.10 is the minimum version, re-enable check B905 for zip + strict +extend-select = B9 diff --git a/cwltest/compare.py b/cwltest/compare.py index 2278a86..5374202 100644 --- a/cwltest/compare.py +++ b/cwltest/compare.py @@ -29,7 +29,7 @@ def _check_keys( compare(expected.get(k), actual.get(k)) except CompareFail as e: raise CompareFail.format( - expected, actual, f"field '{k}' failed comparison: {str(e)}" + expected, actual, f"field {k!r} failed comparison: {str(e)}" ) from e @@ -54,7 +54,7 @@ def _compare_dict(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: compare(expected[c], actual.get(c)) except CompareFail as e: raise CompareFail.format( - expected, actual, f"failed comparison for key '{c}': {e}" + expected, actual, f"failed comparison for key {c!r}: {e}" ) from e extra_keys = set(actual.keys()).difference(list(expected.keys())) for k in extra_keys: diff --git a/cwltest/plugin.py b/cwltest/plugin.py index d59c2f5..c3c0c6b 100644 --- a/cwltest/plugin.py +++ b/cwltest/plugin.py @@ -236,24 +236,24 @@ def collect(self) -> Iterator[CWLItem]: if include and name not in include: item.add_marker( pytest.mark.skip( - reason=f"Test '{name}' is not in the include list: {','.join(include)}." + reason=f"Test {name!r} is not in the include list: {','.join(include)}." ) ) elif exclude and name in exclude: item.add_marker( - pytest.mark.skip(reason=f"Test '{name}' is in the exclude list.") + pytest.mark.skip(reason=f"Test {name!r} is in the exclude list.") ) elif tags and not tags.intersection(entry_tags): item.add_marker( pytest.mark.skip( - reason=f"Test '{name}' with tags {','.join(entry_tags)}" + reason=f"Test {name!r} with tags {','.join(entry_tags)}" f" doesn't have a tag on the allowed tag list: {','.join(tags)}." ) ) elif exclude_tags and exclude_tags.intersection(entry_tags): item.add_marker( pytest.mark.skip( - reason=f"Test '{name}' has one or more tags on the exclusion " + reason=f"Test {name!r} has one or more tags on the exclusion " f" tag list: {','.join(exclude_tags.intersection(entry_tags))}." ) ) diff --git a/cwltest/utils.py b/cwltest/utils.py index d47f376..60413ad 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -122,7 +122,7 @@ def _clean_ruamel(obj: Any) -> Any: return typ(obj) if obj is None: return None - raise Exception(f"Unsupported type {type(obj)} of '{obj}'.") + raise Exception(f"Unsupported type {type(obj)} of {obj!r}.") def generate_badges( @@ -184,9 +184,7 @@ def load_and_validate_tests(path: str) -> Tuple[Any, Dict[str, Any]]: if not isinstance(avsc_names, schema_salad.avro.schema.Names): print(avsc_names) - raise ValidationException( - f"Wrong instance for avsc_names: {type(avsc_names)}" - ) + raise ValidationException(f"Wrong instance for avsc_names: {type(avsc_names)}") tests, metadata = schema_salad.schema.load_and_validate( document_loader, avsc_names, path, True diff --git a/setup.cfg b/setup.cfg index aae8e39..cf9fe0a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,8 +1,3 @@ -[flake8] -ignore = E124,E128,E129,E201,E202,E225,E226,E231,E265,E271,E302,E303,F401,E402,E501,W503,E731,F811,F821,F841 -max-line-length = 88 -extend-ignore = E203, W503 - [aliases] test=pytest diff --git a/tests/test_compare.py b/tests/test_compare.py index 86d456e..687f177 100644 --- a/tests/test_compare.py +++ b/tests/test_compare.py @@ -139,22 +139,26 @@ def test_compare_directory_failure_different_listing() -> None: "basename": "baz.txt", "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709", "class": "File", - "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/baz.txt", + "location": "file:///var/folders/8x/" + "2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/baz.txt", "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/baz.txt", "size": 0, }, { "basename": "foo", "class": "Directory", - "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/foo", + "location": "file:///var/folders/8x/" + "2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/foo", "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/foo", "listing": [ { "basename": "bar.txt", "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80775", "class": "File", - "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/foo/bar.txt", - "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/foo/bar.txt", + "location": "file:///var/folders/8x/" + "2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/foo/bar.txt", + "path": "/var/folders/8x/" + "2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/foo/bar.txt", "size": 0, } ], @@ -202,7 +206,8 @@ def test_compare_directory_failure_no_listing() -> None: "basename": "baz.txt", "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709", "class": "File", - "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/baz.txt", + "location": "file:///var/folders/8x/" + "2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/baz.txt", "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/stuff/baz.txt", "size": 0, }, From 8b23a7b878c71fd75a6e15af105990baf8b9cca5 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Mon, 13 Feb 2023 18:18:38 +0100 Subject: [PATCH 064/165] ci: skip linting on py3.6 --- .github/workflows/ci-tests.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index ddd8e49..22e4357 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -27,6 +27,9 @@ jobs: - py-ver-major: 3 py-ver-minor: 6 step: mypy + - py-ver-major: 3 + py-ver-minor: 6 + step: lint env: py-semver: ${{ format('{0}.{1}', matrix.py-ver-major, matrix.py-ver-minor) }} @@ -34,6 +37,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Set up Python uses: actions/setup-python@v4 @@ -48,7 +53,7 @@ jobs: - name: Upgrade setuptools and install tox run: | pip install -U pip setuptools wheel - pip install tox tox-gh-actions + pip install "tox<4" "tox-gh-actions<3" - name: MyPy cache if: ${{ matrix.step == 'mypy' }} @@ -77,8 +82,8 @@ jobs: step: [lintreadme, pydocstyle] env: - py-semver: "3.10" - TOXENV: ${{ format('py310-{0}', matrix.step) }} + py-semver: "3.11" + TOXENV: ${{ format('py311-{0}', matrix.step) }} steps: - uses: actions/checkout@v3 @@ -98,7 +103,7 @@ jobs: - name: Upgrade setuptools and install tox run: | pip install -U pip setuptools wheel - pip install tox tox-gh-actions + pip install "tox<4" "tox-gh-actions<3" - if: ${{ matrix.step == 'pydocstyle' && github.event_name == 'pull_request'}} name: Create local branch for diff-quality for PRs @@ -118,7 +123,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.10" # quoted, otherwise that turns into the number 3.1 + python-version: "3.11" cache: pip cache-dependency-path: | requirements.txt From 00e011bb92a5b32880ee5dd4c943c303c05756b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Feb 2023 17:27:12 +0000 Subject: [PATCH 065/165] Bump sphinx-rtd-theme from 1.1.1 to 1.2.0 Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 1.1.1 to 1.2.0. - [Release notes](https://github.com/readthedocs/sphinx_rtd_theme/releases) - [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst) - [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/1.1.1...1.2.0) --- updated-dependencies: - dependency-name: sphinx-rtd-theme dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index b8611de..d4fbc5d 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ sphinx >= 2.2 -sphinx-rtd-theme==1.1.1 +sphinx-rtd-theme==1.2.0 sphinx-autoapi sphinx-autodoc-typehints typed_ast;python_version<'3.8' From 65736b9745ef417ccff27cb1dbcef1596d004c45 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 01:31:48 +0000 Subject: [PATCH 066/165] Bump mypy from 1.0.0 to 1.0.1 Bumps [mypy](https://github.com/python/mypy) from 1.0.0 to 1.0.1. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v1.0.0...v1.0.1) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 671641f..f405f74 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.0.0 +mypy==1.0.1 types-setuptools types-requests types-PyYAML From 821f4e91a0a2a6fe8f2152ac457932759912b450 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Mar 2023 00:58:31 +0000 Subject: [PATCH 067/165] Bump mypy from 1.0.1 to 1.1.1 Bumps [mypy](https://github.com/python/mypy) from 1.0.1 to 1.1.1. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v1.0.1...v1.1.1) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index f405f74..d5593cc 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.0.1 +mypy==1.1.1 types-setuptools types-requests types-PyYAML From d9910739486bf037a7d483c6c8ef4c1747e88194 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Mar 2023 00:58:03 +0000 Subject: [PATCH 068/165] Update black requirement from ~=23.1 to ~=23.3 Updates the requirements on [black](https://github.com/psf/black) to permit the latest version. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.1.0...23.3.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index 4ac7321..75c59ca 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ diff_cover -black ~= 23.1 +black ~= 23.3 pylint pep257 pydocstyle From 6a7cf28fb0b9cb6b0ffeecaaff8b7d0c9d2aa6d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Apr 2023 00:57:43 +0000 Subject: [PATCH 069/165] Bump mypy from 1.1.1 to 1.2.0 Bumps [mypy](https://github.com/python/mypy) from 1.1.1 to 1.2.0. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v1.1.1...v1.2.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index d5593cc..93518b7 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.1.1 +mypy==1.2.0 types-setuptools types-requests types-PyYAML From 6b4a7bc3bb95460ebb4a3dfa9d00ea8bfe908c64 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 May 2023 00:57:49 +0000 Subject: [PATCH 070/165] Bump mypy from 1.2.0 to 1.3.0 Bumps [mypy](https://github.com/python/mypy) from 1.2.0 to 1.3.0. - [Commits](https://github.com/python/mypy/compare/v1.2.0...v1.3.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 93518b7..f26d55f 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.2.0 +mypy==1.3.0 types-setuptools types-requests types-PyYAML From 5cd65d552df4673f3269f5bf3a8b9e8a5280cc8e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 May 2023 00:57:57 +0000 Subject: [PATCH 071/165] Bump sphinx-rtd-theme from 1.2.0 to 1.2.1 Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 1.2.0 to 1.2.1. - [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst) - [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/1.2.0...1.2.1) --- updated-dependencies: - dependency-name: sphinx-rtd-theme dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index d4fbc5d..be677f9 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ sphinx >= 2.2 -sphinx-rtd-theme==1.2.0 +sphinx-rtd-theme==1.2.1 sphinx-autoapi sphinx-autodoc-typehints typed_ast;python_version<'3.8' From 4c57396b9063988a296dc99fac5ecf03b2c44302 Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Sat, 27 May 2023 11:12:12 +0200 Subject: [PATCH 072/165] Validate actual file properties such as `checksum` A re-do of https://github.com/common-workflow-language/cwltest/pull/146 Co-Authored-By: Michael R. Crusoe --- cwltest/compare.py | 136 +++++++++++++++++++++++++++++++++++------- tests/test_compare.py | 123 +++++++++++++++++++++++++++++++++++++- tox.ini | 4 +- 3 files changed, 236 insertions(+), 27 deletions(-) diff --git a/cwltest/compare.py b/cwltest/compare.py index 5374202..8a4e89e 100644 --- a/cwltest/compare.py +++ b/cwltest/compare.py @@ -1,7 +1,10 @@ """Compare utilities for CWL objects.""" +import hashlib import json -from typing import Any, Dict, Optional, Set +import os.path +import urllib.parse +from typing import Any, Callable, Dict, Optional, Set class CompareFail(Exception): @@ -22,11 +25,11 @@ def format( def _check_keys( - keys: Set[str], expected: Dict[str, Any], actual: Dict[str, Any] + keys: Set[str], expected: Dict[str, Any], actual: Dict[str, Any], skip_details: bool ) -> None: for k in keys: try: - compare(expected.get(k), actual.get(k)) + compare(expected.get(k), actual.get(k), skip_details) except CompareFail as e: raise CompareFail.format( expected, actual, f"field {k!r} failed comparison: {str(e)}" @@ -48,10 +51,12 @@ def _compare_contents(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: ) -def _compare_dict(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: +def _compare_dict( + expected: Dict[str, Any], actual: Dict[str, Any], skip_details: bool +) -> None: for c in expected: try: - compare(expected[c], actual.get(c)) + compare(expected[c], actual.get(c), skip_details) except CompareFail as e: raise CompareFail.format( expected, actual, f"failed comparison for key {c!r}: {e}" @@ -62,7 +67,9 @@ def _compare_dict(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: raise CompareFail.format(expected, actual, "unexpected key '%s'" % k) -def _compare_directory(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: +def _compare_directory( + expected: Dict[str, Any], actual: Dict[str, Any], skip_details: bool +) -> None: if actual.get("class") != "Directory": raise CompareFail.format( expected, actual, "expected object with a class 'Directory'" @@ -75,7 +82,7 @@ def _compare_directory(expected: Dict[str, Any], actual: Dict[str, Any]) -> None found = False for j in actual["listing"]: try: - compare(i, j) + compare(i, j, skip_details) found = True break except CompareFail: @@ -86,19 +93,32 @@ def _compare_directory(expected: Dict[str, Any], actual: Dict[str, Any]) -> None actual, "%s not found" % json.dumps(i, indent=4, sort_keys=True), ) - _compare_file(expected, actual) + _compare_file(expected, actual, skip_details) -def _compare_file(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: - _compare_location(expected, actual) +def _compare_file( + expected: Dict[str, Any], actual: Dict[str, Any], skip_details: bool +) -> None: + _compare_location(expected, actual, skip_details) if "contents" in expected: _compare_contents(expected, actual) - other_keys = set(expected.keys()) - {"path", "location", "listing", "contents"} - _check_keys(other_keys, expected, actual) - _check_keys(other_keys, expected, actual) - - -def _compare_location(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: + if actual.get("class") == "File" and not skip_details: + _compare_checksum(expected, actual) + _compare_size(expected, actual) + other_keys = set(expected.keys()) - { + "path", + "location", + "listing", + "contents", + "checksum", + "size", + } + _check_keys(other_keys, expected, actual, skip_details) + + +def _compare_location( + expected: Dict[str, Any], actual: Dict[str, Any], skip_details: bool +) -> None: if "path" in expected: comp = "path" if "path" not in actual: @@ -109,7 +129,19 @@ def _compare_location(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: return if actual.get("class") == "Directory": actual[comp] = actual[comp].rstrip("/") - + exist_fun: Callable[[str], bool] = os.path.isdir + else: + exist_fun = os.path.isfile + if "path" in actual: + path = urllib.parse.urlparse(actual["path"]).path + else: + path = urllib.parse.urlparse(actual["location"]).path + if not exist_fun(path) and not skip_details: + raise CompareFail.format( + expected, + actual, + f"{actual[comp]} does not exist", + ) if expected[comp] != "Any" and ( not ( actual[comp].endswith("/" + expected[comp]) @@ -123,7 +155,67 @@ def _compare_location(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: ) -def compare(expected: Any, actual: Any) -> None: +def _compare_checksum(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: + if "path" in actual: + path = urllib.parse.urlparse(actual["path"]).path + else: + path = urllib.parse.urlparse(actual["location"]).path + checksum = hashlib.sha1() # nosec + with open(path, "rb") as f: + contents = f.read(1024 * 1024) + while contents != b"": + checksum.update(contents) + contents = f.read(1024 * 1024) + actual_checksum_on_disk = f"sha1${checksum.hexdigest()}" + if "checksum" in actual: + actual_checksum_declared = actual["checksum"] + if actual_checksum_on_disk != actual_checksum_declared: + raise CompareFail.format( + expected, + actual, + "Output file checksums do not match: actual " + f"{actual_checksum_on_disk!r} on disk is not equal to actual " + f"{actual_checksum_declared!r} in the output object", + ) + if "checksum" in expected: + expected_checksum = expected["checksum"] + if expected_checksum != actual_checksum_on_disk: + raise CompareFail.format( + expected, + actual, + "Output file checksums do not match: actual " + f"{actual_checksum_on_disk!r} is not equal to expected {expected_checksum!r}", + ) + + +def _compare_size(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: + if "path" in actual: + path = urllib.parse.urlparse(actual["path"]).path + else: + path = urllib.parse.urlparse(actual["location"]).path + actual_size_on_disk = os.path.getsize(path) + if "size" in actual: + actual_size_declared = actual["size"] + if actual_size_on_disk != actual_size_declared: + raise CompareFail.format( + expected, + actual, + "Output file sizes do not match: actual " + f"{actual_size_on_disk!r} on disk is not equal to actual " + f"{actual_size_declared!r}' in the output object", + ) + if "size" in expected: + expected_size = expected["size"] + if expected_size != actual_size_on_disk: + raise CompareFail.format( + expected, + actual, + "Output file sizes do not match: actual " + f"{actual_size_on_disk!r} is not equal to expected {expected_size!r}", + ) + + +def compare(expected: Any, actual: Any, skip_details: bool = False) -> None: """Compare two CWL objects.""" if expected == "Any": return @@ -136,11 +228,11 @@ def compare(expected: Any, actual: Any) -> None: raise CompareFail.format(expected, actual) if expected.get("class") == "File": - _compare_file(expected, actual) + _compare_file(expected, actual, skip_details) elif expected.get("class") == "Directory": - _compare_directory(expected, actual) + _compare_directory(expected, actual, skip_details) else: - _compare_dict(expected, actual) + _compare_dict(expected, actual, skip_details) elif isinstance(expected, list): if not isinstance(actual, list): @@ -150,7 +242,7 @@ def compare(expected: Any, actual: Any) -> None: raise CompareFail.format(expected, actual, "lengths don't match") for c in range(0, len(expected)): try: - compare(expected[c], actual[c]) + compare(expected[c], actual[c], skip_details) except CompareFail as e: raise CompareFail.format(expected, actual, e) from e else: diff --git a/tests/test_compare.py b/tests/test_compare.py index 687f177..6491f8d 100644 --- a/tests/test_compare.py +++ b/tests/test_compare.py @@ -1,7 +1,9 @@ +import os +from pathlib import Path from typing import Any, Dict import pytest -from cwltest.compare import CompareFail, compare +from cwltest.compare import CompareFail, _compare_directory, _compare_file, compare from .util import get_data @@ -37,6 +39,7 @@ def test_compare_contents_success() -> None: "size": 2, "class": "File", "contents": "2\n", + "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", } actual = { "basename": "cores.txt", @@ -49,6 +52,120 @@ def test_compare_contents_success() -> None: compare(expected, actual) +def test_compare_contents_not_exist() -> None: + expected = { + "location": "cores.txt", + "class": "File", + } + actual = { + "basename": "cores.txt", + "class": "File", + "location": "file:///var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", + "path": "/none/exist/path/to/cores.txt", + "size": 2, + } + with pytest.raises(CompareFail): + _compare_file(expected, actual, False) + + +def test_compare_file_different_size(tmp_path: Path) -> None: + expected = { + "location": "cores.txt", + "size": 2, + "class": "File", + } + + path = tmp_path / "cores.txt" + with open(path, "w") as f: + f.write("hello") + + actual = { + "basename": "cores.txt", + "class": "File", + "location": str(path), + } + with pytest.raises(CompareFail): + _compare_file(expected, actual, False) + + +def test_compare_file_different_checksum(tmp_path: Path) -> None: + expected = { + "location": "cores.txt", + "class": "File", + "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7a", + } + + path = tmp_path / "cores.txt" + with open(path, "w") as f: + f.write("hello") + + actual = { + "basename": "cores.txt", + "class": "File", + "location": str(path), + } + with pytest.raises(CompareFail): + _compare_file(expected, actual, False) + + +def test_compare_file_inconsistent_size(tmp_path: Path) -> None: + expected = { + "location": "cores.txt", + "class": "File", + } + + path = tmp_path / "cores.txt" + with open(path, "w") as f: + f.write("hello") + + actual = { + "basename": "cores.txt", + "class": "File", + "location": str(path), + "size": 65535, + } + with pytest.raises(CompareFail): + _compare_file(expected, actual, False) + + +def test_compare_file_inconsistent_checksum(tmp_path: Path) -> None: + expected = { + "location": "cores.txt", + "class": "File", + } + + path = tmp_path / "cores.txt" + with open(path, "w") as f: + f.write("hello") + + actual = { + "basename": "cores.txt", + "checksum": "inconsistent-checksum", + "class": "File", + "location": str(path), + } + with pytest.raises(CompareFail): + _compare_file(expected, actual, False) + + +def test_compare_directory(tmp_path: Path) -> None: + expected = { + "location": "dir", + "class": "Directory", + "listing": [], + } + + path = tmp_path / "dir" + os.makedirs(path) + + actual = { + "class": "Directory", + "location": str(path), + "listing": [], + } + _compare_directory(expected, actual, False) + + def test_compare_directory_success() -> None: expected = { "stuff": { @@ -100,7 +217,7 @@ def test_compare_directory_success() -> None: ], } } - compare(expected, actual) + compare(expected, actual, skip_details=True) def test_compare_directory_failure_different_listing() -> None: @@ -270,7 +387,7 @@ def test_compare_file_success() -> None: "path": "/var/folders/8x/2df05_7j20j6r8y81w4qf43r0000gn/T/tmpG0EkrS/cores.txt", "size": 2, } - compare(expected, actual) + compare(expected, actual, skip_details=True) def test_compare_list_failure_missing() -> None: diff --git a/tox.ini b/tox.ini index 0ac4e44..a841a1e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] envlist = - py{36,37,38,39,310,311}-lint, + py{37,38,39,310,311}-lint, py{36,37,38,39,310,311}-unit, py{36,37,38,39,310,311}-bandit, py{37,38,39,310,311}-mypy, @@ -58,7 +58,7 @@ commands = py{36,37,38,39,310,311}-unit: python -m pip install -U pip setuptools wheel py{36,37,38,39,310,311}-unit: python -m pytest --cov --cov-config={toxinidir}/.coveragerc --cov-append {posargs} py{36,37,38,39,310,311}-unit: coverage xml - py{36,37,38,39,310,311}-bandit: bandit --recursive cwltest --exclude tests/* + py{36,37,38,39,310,311}-bandit: bandit --recursive cwltest py{36,37,38,39,310,311}-lint: make flake8 py{36,37,38,39,310,311}-lint: make format-check py{37,38,39,310,311}-mypy: make mypy From 4b106d3d2188c342604096cad3079ee9cd4a3f99 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Wed, 7 Jun 2023 15:06:09 +0100 Subject: [PATCH 073/165] include missing files in sdist --- MANIFEST.in | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 1eab7bf..3aec21c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,7 @@ -include Makefile gittaggers.py test-requirements.txt mypy-requirements.txt requirements.txt -include cwltest/cwltest-schema.yml +include Makefile gittaggers.py test-requirements.txt mypy-requirements.txt requirements.txt tox.ini mypy.ini +include dev-requirements.txt .flake8 .coveragerc release-test.sh +include docs/Makefile docs/conf.py docs/requirements.txt docs/_static/favicon.ico docs/*.rst +include cwltest/*.yml include tests/* include tests/test-data/* include tests/test-data/v1.0/* From 0f9117efaa811494135983f732bf55266d4b4ccb Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Wed, 7 Jun 2023 16:50:06 +0100 Subject: [PATCH 074/165] test_catories path fixes --- tests/test_categories.py | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/tests/test_categories.py b/tests/test_categories.py index c6461e9..ceb2f3b 100644 --- a/tests/test_categories.py +++ b/tests/test_categories.py @@ -14,15 +14,10 @@ def test_unsupported_with_required_tests() -> None: cwl_runner = get_data("tests/test-data/mock_cwl_runner.py") - args = [ - "--test", - schema_salad.ref_resolver.file_uri( - get_data("tests/test-data/required-unsupported.yml") - ), - ] cwd = os.getcwd() + os.chdir(get_data("tests/test-data/")) + args = ["--test", "required-unsupported.yml"] try: - os.chdir(get_data("tests/test-data/")) error_code, stdout, stderr = run_with_mock_cwl_runner(args) finally: os.chdir(cwd) @@ -35,21 +30,19 @@ def test_unsupported_with_required_tests() -> None: else: q = "" assert ( - "The `id` field is missing.{n}" - "The `id` field is missing.{n}" - "Test [1/2] Required test that is unsupported (without tags){n}" - "{n}" - "Test 1 failed: {cwl_runner} --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" - "Required test that is unsupported (without tags){n}" - "Does not support required feature{n}" - "Test [2/2] Required test that is unsupported (with tags){n}" - "{n}" - "Test 2 failed: {cwl_runner} --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" - "Required test that is unsupported (with tags){n}" - "Does not support required feature{n}" - "0 tests passed, 2 failures, 0 unsupported features{n}".format( - cwl_runner=cwl_runner, n=n, p=p, q=q - ) + f"The `id` field is missing.{n}" + f"The `id` field is missing.{n}" + f"Test [1/2] Required test that is unsupported (without tags){n}" + f"{n}" + f"Test 1 failed: {cwl_runner} --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" + f"Required test that is unsupported (without tags){n}" + f"Does not support required feature{n}" + f"Test [2/2] Required test that is unsupported (with tags){n}" + f"{n}" + f"Test 2 failed: {cwl_runner} --quiet return-unsupported.cwl {q}v1.0{p}cat-job.json{q}{n}" + f"Required test that is unsupported (with tags){n}" + f"Does not support required feature{n}" + f"0 tests passed, 2 failures, 0 unsupported features{n}" ) == stderr From 120ca38a07ab8c17af5f92633eaf5c15ce96cbb5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jun 2023 00:58:03 +0000 Subject: [PATCH 075/165] Bump sphinx-rtd-theme from 1.2.1 to 1.2.2 Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 1.2.1 to 1.2.2. - [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst) - [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/1.2.1...1.2.2) --- updated-dependencies: - dependency-name: sphinx-rtd-theme dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index be677f9..4820ced 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ sphinx >= 2.2 -sphinx-rtd-theme==1.2.1 +sphinx-rtd-theme==1.2.2 sphinx-autoapi sphinx-autodoc-typehints typed_ast;python_version<'3.8' From 1e60b9ecacd3041114788500dda0493046e564b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Jun 2023 00:58:07 +0000 Subject: [PATCH 076/165] Bump mypy from 1.3.0 to 1.4.0 Bumps [mypy](https://github.com/python/mypy) from 1.3.0 to 1.4.0. - [Commits](https://github.com/python/mypy/compare/v1.3.0...v1.4.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index f26d55f..e4ebae2 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.3.0 +mypy==1.4.0 types-setuptools types-requests types-PyYAML From e0e7b4d1ff5e00255b6580e884d40a4fce2c6e79 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Jun 2023 01:06:13 +0000 Subject: [PATCH 077/165] Bump mypy from 1.4.0 to 1.4.1 Bumps [mypy](https://github.com/python/mypy) from 1.4.0 to 1.4.1. - [Commits](https://github.com/python/mypy/compare/v1.4.0...v1.4.1) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index e4ebae2..b5de881 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.4.0 +mypy==1.4.1 types-setuptools types-requests types-PyYAML From cf6586673fa8deee9740b15b5aa84039bfc3e359 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Jul 2023 00:37:48 +0000 Subject: [PATCH 078/165] Update black requirement from ~=23.3 to ~=23.7 Updates the requirements on [black](https://github.com/psf/black) to permit the latest version. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.3.0...23.7.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index 75c59ca..a44e618 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ diff_cover -black ~= 23.3 +black ~= 23.7 pylint pep257 pydocstyle From c6b8baf70b9568d3ca1ede0da66396b9c85c85a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Aug 2023 00:34:09 +0000 Subject: [PATCH 079/165] Bump sphinx-rtd-theme from 1.2.2 to 1.3.0 Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 1.2.2 to 1.3.0. - [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst) - [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/1.2.2...1.3.0) --- updated-dependencies: - dependency-name: sphinx-rtd-theme dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 4820ced..bd71cd1 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ sphinx >= 2.2 -sphinx-rtd-theme==1.2.2 +sphinx-rtd-theme==1.3.0 sphinx-autoapi sphinx-autodoc-typehints typed_ast;python_version<'3.8' From 1a1a5ff03b5c14476ace4d5867867c95257da0fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Aug 2023 08:13:08 +0000 Subject: [PATCH 080/165] Bump mypy from 1.4.1 to 1.5.1 Bumps [mypy](https://github.com/python/mypy) from 1.4.1 to 1.5.1. - [Commits](https://github.com/python/mypy/compare/v1.4.1...v1.5.1) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index b5de881..e28b381 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.4.1 +mypy==1.5.1 types-setuptools types-requests types-PyYAML From fc8cf0bcf0f67b60760b26a6f94ee498d1b664ee Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 25 Aug 2023 14:46:46 +0200 Subject: [PATCH 081/165] testing: drop Python 3.7, add 3.12 --- .github/workflows/ci-tests.yml | 5 ++- setup.py | 2 +- tox.ini | 70 +++++++++++++++++----------------- 3 files changed, 39 insertions(+), 38 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 22e4357..55e7434 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -21,7 +21,7 @@ jobs: matrix: # The README.rst file mentions the versions tested, please update it as well py-ver-major: [3] - py-ver-minor: [6, 7, 8, 9, 10, 11] + py-ver-minor: [6, 8, 9, 10, 11, 12] step: [lint, unit, mypy, bandit] exclude: - py-ver-major: 3 @@ -44,6 +44,7 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ env.py-semver }} + allow-prereleases: true cache: pip cache-dependency-path: | requirements.txt @@ -75,7 +76,7 @@ jobs: tox-style: name: CI linters via Tox - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: matrix: diff --git a/setup.py b/setup.py index 5b9c52f..60e258f 100644 --- a/setup.py +++ b/setup.py @@ -65,11 +65,11 @@ "Operating System :: MacOS :: MacOS X", "Development Status :: 5 - Production/Stable", "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Typing :: Typed", ], ) diff --git a/tox.ini b/tox.ini index a841a1e..690fe66 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,11 @@ [tox] envlist = - py{37,38,39,310,311}-lint, - py{36,37,38,39,310,311}-unit, - py{36,37,38,39,310,311}-bandit, - py{37,38,39,310,311}-mypy, - py310-lintreadme, - py310-pydocstyle + py3{8,9,10,11,12}-lint, + py3{6,8,9,10,11,12}-unit, + py3{6,8,9,10,11,12}-bandit, + py3{8,9,10,11,12}-mypy, + py311-lintreadme, + py311-pydocstyle skip_missing_interpreters = True @@ -17,64 +17,64 @@ testpaths = tests [gh-actions] python = 3.6: py36 - 3.7: py37 3.8: py38 3.9: py39 3.10: py310 3.11: py311 + 3.12: py312 [testenv] skipsdist = py3{6,7,8,9,10,11}-!{unit,mypy,lintreadme} = True description = - py{36,37,38,39,310,311}-unit: Run the unit tests - py{36,37,38,39,310,311}-lint: Lint the Python code - py{36,37,38,39,310,311}-bandit: Search for common security issues - py{37,38,39,310,311}-mypy: Check for type safety - py310-pydocstyle: docstring style checker - py310-lintreadme: Lint the README.rst->.md conversion + py3{6,8,9,10,11,12}-unit: Run the unit tests + py3{6,8,9,10,11,12}-lint: Lint the Python code + py3{6,8,9,10,11,12}-bandit: Search for common security issues + py3{8,9,10,11,12}-mypy: Check for type safety + py311-pydocstyle: docstring style checker + py311-lintreadme: Lint the README.rst->.md conversion passenv = CI GITHUB_* deps = - py{36,37,38,39,310,311}-{unit,mypy}: -rrequirements.txt - py{36,37,38,39,310,311}-{unit,mypy}: -rtest-requirements.txt - py{36,37,38,39,310,311}-lint: flake8-bugbear - py{36,37,38,39,310,311}-lint: black~=23.1 - py{36,37,38,39,310,311}-bandit: bandit - py{37,38,39,310,311}-mypy: -rmypy-requirements.txt + py3{6,8,9,10,11,12}-{unit,mypy}: -rrequirements.txt + py3{6,8,9,10,11,12}-{unit,mypy}: -rtest-requirements.txt + py3{6,8,9,10,11,12}-lint: flake8-bugbear + py3{6,8,9,10,11,12}-lint: black~=23.1 + py3{6,8,9,10,11,12}-bandit: bandit + py3{8,9,10,11,12}-mypy: -rmypy-requirements.txt setenv = - py{36,37,38,39,310,311}-unit: LC_ALL = C.UTF-8 + py3{6,8,3,10,11,12}-unit: LC_ALL = C.UTF-8 COV_CORE_SOURCE=cwltest COV_CORE_CONFIG={toxinidir}/.coveragerc COV_CORE_DATAFILE={toxinidir}/.coverage.eager commands = - py{36,37,38,39,310,311}-unit: python -m pip install -U pip setuptools wheel - py{36,37,38,39,310,311}-unit: python -m pytest --cov --cov-config={toxinidir}/.coveragerc --cov-append {posargs} - py{36,37,38,39,310,311}-unit: coverage xml - py{36,37,38,39,310,311}-bandit: bandit --recursive cwltest - py{36,37,38,39,310,311}-lint: make flake8 - py{36,37,38,39,310,311}-lint: make format-check - py{37,38,39,310,311}-mypy: make mypy - py37-mypy: make mypy_3.6 + py3{6,8,9,10,11,12}-unit: python -m pip install -U pip setuptools wheel + py3{6,8,9,10,11,12}-unit: python -m pytest --cov --cov-config={toxinidir}/.coveragerc --cov-append {posargs} + py3{6,8,9,10,11,12}-unit: coverage xml + py3{6,8,9,10,11,12}-bandit: bandit --recursive cwltest + py3{6,8,9,10,11,12}-lint: make flake8 + py3{6,8,9,10,11,12}-lint: make format-check + py3{8,9,10,11,12}-mypy: make mypy + py38-mypy: make mypy_3.6 allowlist_externals = - py{36,37,38,39,310,311}-lint: flake8 - py{36,37,38,39,310,311}-lint: black - py{36,37,38,39,310,311}-{mypy,shellcheck,lint,unit}: make + py3{6,8,9,10,11,12}-lint: flake8 + py3{6,8,9,10,11,12}-lint: black + py3{6,8,9,10,11,12}-{mypy,shellcheck,lint,unit}: make skip_install = - py{36,37,38,39,310,311}-lint: true - py{36,37,38,39,310,311}-bandit: true + py3{6,8,9,10,11,12}-lint: true + py3{6,8,9,10,11,12}-bandit: true -[testenv:py310-pydocstyle] +[testenv:py311-pydocstyle] allowlist_externals = make commands = make diff_pydocstyle_report deps = @@ -82,7 +82,7 @@ deps = diff-cover skip_install = true -[testenv:py310-lintreadme] +[testenv:py311-lintreadme] description = Lint the README.rst->.md conversion commands = python -m build --outdir {distdir} From 44c0ad84ed2637c574f085fb5a575240b9c1d198 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 00:06:48 +0000 Subject: [PATCH 082/165] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci-tests.yml | 6 +++--- .github/workflows/codeql-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 55e7434..2bb6680 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -36,7 +36,7 @@ jobs: TOXENV: ${{ format('py{0}{1}-{2}', matrix.py-ver-major, matrix.py-ver-minor, matrix.step) }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 @@ -87,7 +87,7 @@ jobs: TOXENV: ${{ format('py311-{0}', matrix.step) }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 @@ -119,7 +119,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 292544f..8c5fc31 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. From f8e68b865d453611523a25596dc2ae4936f0e81e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 00:24:45 +0000 Subject: [PATCH 083/165] Update black requirement from ~=23.7 to ~=23.9 Updates the requirements on [black](https://github.com/psf/black) to permit the latest version. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.7.0...23.9.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index a44e618..8be2342 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ diff_cover -black ~= 23.7 +black ~= 23.9 pylint pep257 pydocstyle From 3a36d096ba9dfa9077aef8190e0e0f0a3294652e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Oct 2023 00:30:49 +0000 Subject: [PATCH 084/165] Bump mypy from 1.5.1 to 1.6.0 Bumps [mypy](https://github.com/python/mypy) from 1.5.1 to 1.6.0. - [Commits](https://github.com/python/mypy/compare/v1.5.1...v1.6.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index e28b381..357d788 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.5.1 +mypy==1.6.0 types-setuptools types-requests types-PyYAML From f9c8f1c459df4f976a4dd7ee4145548293432f0d Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Wed, 11 Oct 2023 09:21:58 +0200 Subject: [PATCH 085/165] Drop Python 3.6 testing This is now a Python 3.8+ codebase Default to Python 3.12 for release testing and others --- .github/workflows/ci-tests.yml | 16 +++------ Makefile | 6 ++-- README.rst | 2 +- cwltest/argparser.py | 3 +- cwltest/compare.py | 3 +- cwltest/plugin.py | 8 ++--- dev-requirements.txt | 1 + release-test.sh | 4 +-- requirements.txt | 1 - setup.py | 3 +- tox.ini | 60 ++++++++++++++++------------------ 11 files changed, 45 insertions(+), 62 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 2bb6680..9222ed9 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -21,15 +21,8 @@ jobs: matrix: # The README.rst file mentions the versions tested, please update it as well py-ver-major: [3] - py-ver-minor: [6, 8, 9, 10, 11, 12] + py-ver-minor: [8, 9, 10, 11, 12] step: [lint, unit, mypy, bandit] - exclude: - - py-ver-major: 3 - py-ver-minor: 6 - step: mypy - - py-ver-major: 3 - py-ver-minor: 6 - step: lint env: py-semver: ${{ format('{0}.{1}', matrix.py-ver-major, matrix.py-ver-minor) }} @@ -44,7 +37,6 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ env.py-semver }} - allow-prereleases: true cache: pip cache-dependency-path: | requirements.txt @@ -83,8 +75,8 @@ jobs: step: [lintreadme, pydocstyle] env: - py-semver: "3.11" - TOXENV: ${{ format('py311-{0}', matrix.step) }} + py-semver: "3.12" + TOXENV: ${{ format('py312-{0}', matrix.step) }} steps: - uses: actions/checkout@v4 @@ -124,7 +116,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.11" + python-version: "3.12" cache: pip cache-dependency-path: | requirements.txt diff --git a/Makefile b/Makefile index ced0a68..0e5889e 100644 --- a/Makefile +++ b/Makefile @@ -168,11 +168,9 @@ mypy3: mypy mypy: $(filter-out setup.py gittagger.py,$(PYSOURCES)) MYPYPATH=$$MYPYPATH:mypy-stubs mypy $^ -mypy_3.6: $(filter-out setup.py gittagger.py,$(PYSOURCES)) - MYPYPATH=$$MYPYPATH:mypy-stubs mypy --python-version 3.6 $^ - pyupgrade: $(filter-out schema_salad/metaschema.py,$(PYSOURCES)) - pyupgrade --exit-zero-even-if-changed --py36-plus $^ + pyupgrade --exit-zero-even-if-changed --py38-plus $^ + auto-walrus $^ release-test: FORCE git diff-index --quiet HEAD -- || ( echo You have uncommitted changes, please commit them and try again; false ) diff --git a/README.rst b/README.rst index f6e7e2e..a20438f 100644 --- a/README.rst +++ b/README.rst @@ -32,7 +32,7 @@ This is a testing tool for checking the output of Tools and Workflows described with the Common Workflow Language. Among other uses, it is used to run the CWL conformance tests. -This is written and tested for Python 3.6, 3.7, 3.8, 3.9, 3.10, and 3.11. +This is written and tested for Python 3.8, 3.9, 3.10, 3.11, and 3.12. .. contents:: Table of Contents :local: diff --git a/cwltest/argparser.py b/cwltest/argparser.py index 6cc616d..819c553 100644 --- a/cwltest/argparser.py +++ b/cwltest/argparser.py @@ -107,8 +107,7 @@ def arg_parser() -> argparse.ArgumentParser: help="Create JSON badges and store them in this directory.", ) - pkg = pkg_resources.require("cwltest") - if pkg: + if pkg := pkg_resources.require("cwltest"): ver = f"{sys.argv[0]} {pkg[0].version}" else: ver = "{} {}".format(sys.argv[0], "unknown version") diff --git a/cwltest/compare.py b/cwltest/compare.py index 8a4e89e..f392239 100644 --- a/cwltest/compare.py +++ b/cwltest/compare.py @@ -37,10 +37,9 @@ def _check_keys( def _compare_contents(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: - expected_contents = expected["contents"] with open(actual["path"]) as f: actual_contents = f.read() - if expected_contents != actual_contents: + if (expected_contents := expected["contents"]) != actual_contents: raise CompareFail.format( expected, actual, diff --git a/cwltest/plugin.py b/cwltest/plugin.py index c3c0c6b..40da5f5 100644 --- a/cwltest/plugin.py +++ b/cwltest/plugin.py @@ -13,6 +13,7 @@ Iterator, List, Optional, + Protocol, Set, Tuple, Union, @@ -21,7 +22,6 @@ import pytest from cwltest.compare import CompareFail, compare -from typing_extensions import Protocol from cwltest import REQUIRED, UNSUPPORTED_FEATURE, logger, utils @@ -207,8 +207,7 @@ def _add_global_properties(self) -> None: """Nonfunctional if xdist is installed and anything besides "-n 0" is used.""" from _pytest.junitxml import xml_key - xml = self.config._store.get(xml_key, None) - if xml: + if xml := self.config._store.get(xml_key, None): xml.add_global_property("runner", self.config.getoption("cwl_runner")) xml.add_global_property( "runner_extra_args", self.config.getoption("cwl_args") @@ -381,8 +380,7 @@ def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None: nunsupported, _, ) = utils.parse_results(results, tests) - cwl_badgedir = session.config.getoption("cwl_badgedir") - if cwl_badgedir: + if cwl_badgedir := session.config.getoption("cwl_badgedir"): utils.generate_badges(cwl_badgedir, ntotal, npassed) diff --git a/dev-requirements.txt b/dev-requirements.txt index 8be2342..c77c4c6 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -12,3 +12,4 @@ autoflake flake8-bugbear pyupgrade bandit +auto-walrus diff --git a/release-test.sh b/release-test.sh index d7010b0..1eb6004 100755 --- a/release-test.sh +++ b/release-test.sh @@ -18,8 +18,8 @@ else HEAD=$(git rev-parse HEAD) fi run_tests="bin/py.test -p pytester --pyargs ${module}" -pipver=20.3.3 # minimum required version of pip for Python 3.10 -setuptoolsver=50.0.1 # required for Python 3.10 +pipver=23.1 # minimum required version of pip for Python 3.12 +setuptoolsver=67.6.1 # required for Python 3.12 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" rm -Rf testenv? || /bin/true diff --git a/requirements.txt b/requirements.txt index a15d1b3..bce0adf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,3 @@ schema-salad >= 5.0.20200220195218, < 9 junit-xml >= 1.8 pytest >= 7, < 8 defusedxml -typing-extensions diff --git a/setup.py b/setup.py index 60e258f..1e19380 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ url="https://github.com/common-workflow-language/cwltest", download_url="https://github.com/common-workflow-language/cwltest", license="Apache 2.0", - python_requires=">=3.6, <4", + python_requires=">=3.8, <4", setup_requires=[] + pytest_runner, packages=["cwltest", "cwltest.tests"], package_dir={"cwltest.tests": "tests"}, @@ -64,7 +64,6 @@ "Operating System :: POSIX", "Operating System :: MacOS :: MacOS X", "Development Status :: 5 - Production/Stable", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", diff --git a/tox.ini b/tox.ini index 690fe66..a41f0f0 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,11 @@ [tox] envlist = py3{8,9,10,11,12}-lint, - py3{6,8,9,10,11,12}-unit, - py3{6,8,9,10,11,12}-bandit, + py3{8,9,10,11,12}-unit, + py3{8,9,10,11,12}-bandit, py3{8,9,10,11,12}-mypy, - py311-lintreadme, - py311-pydocstyle + py312-lintreadme, + py312-pydocstyle skip_missing_interpreters = True @@ -16,7 +16,6 @@ testpaths = tests [gh-actions] python = - 3.6: py36 3.8: py38 3.9: py39 3.10: py310 @@ -25,56 +24,55 @@ python = [testenv] skipsdist = - py3{6,7,8,9,10,11}-!{unit,mypy,lintreadme} = True + py3{8,9,10,11,12}-!{unit,mypy,lintreadme} = True description = - py3{6,8,9,10,11,12}-unit: Run the unit tests - py3{6,8,9,10,11,12}-lint: Lint the Python code - py3{6,8,9,10,11,12}-bandit: Search for common security issues + py3{8,9,10,11,12}-unit: Run the unit tests + py3{8,9,10,11,12}-lint: Lint the Python code + py3{8,9,10,11,12}-bandit: Search for common security issues py3{8,9,10,11,12}-mypy: Check for type safety - py311-pydocstyle: docstring style checker - py311-lintreadme: Lint the README.rst->.md conversion + py312-pydocstyle: docstring style checker + py312-lintreadme: Lint the README.rst->.md conversion passenv = CI GITHUB_* deps = - py3{6,8,9,10,11,12}-{unit,mypy}: -rrequirements.txt - py3{6,8,9,10,11,12}-{unit,mypy}: -rtest-requirements.txt - py3{6,8,9,10,11,12}-lint: flake8-bugbear - py3{6,8,9,10,11,12}-lint: black~=23.1 - py3{6,8,9,10,11,12}-bandit: bandit + py3{8,9,10,11,12}-{unit,mypy}: -rrequirements.txt + py3{8,9,10,11,12}-{unit,mypy}: -rtest-requirements.txt + py3{8,9,10,11,12}-lint: flake8-bugbear + py3{8,9,10,11,12}-lint: black~=23.1 + py3{8,9,10,11,12}-bandit: bandit py3{8,9,10,11,12}-mypy: -rmypy-requirements.txt setenv = - py3{6,8,3,10,11,12}-unit: LC_ALL = C.UTF-8 + py3{8,3,10,11,12}-unit: LC_ALL = C.UTF-8 COV_CORE_SOURCE=cwltest COV_CORE_CONFIG={toxinidir}/.coveragerc COV_CORE_DATAFILE={toxinidir}/.coverage.eager commands = - py3{6,8,9,10,11,12}-unit: python -m pip install -U pip setuptools wheel - py3{6,8,9,10,11,12}-unit: python -m pytest --cov --cov-config={toxinidir}/.coveragerc --cov-append {posargs} - py3{6,8,9,10,11,12}-unit: coverage xml - py3{6,8,9,10,11,12}-bandit: bandit --recursive cwltest - py3{6,8,9,10,11,12}-lint: make flake8 - py3{6,8,9,10,11,12}-lint: make format-check + py3{8,9,10,11,12}-unit: python -m pip install -U pip setuptools wheel + py3{8,9,10,11,12}-unit: python -m pytest --cov --cov-config={toxinidir}/.coveragerc --cov-append {posargs} + py3{8,9,10,11,12}-unit: coverage xml + py3{8,9,10,11,12}-bandit: bandit --recursive cwltest + py3{8,9,10,11,12}-lint: make flake8 + py3{8,9,10,11,12}-lint: make format-check py3{8,9,10,11,12}-mypy: make mypy - py38-mypy: make mypy_3.6 allowlist_externals = - py3{6,8,9,10,11,12}-lint: flake8 - py3{6,8,9,10,11,12}-lint: black - py3{6,8,9,10,11,12}-{mypy,shellcheck,lint,unit}: make + py3{8,9,10,11,12}-lint: flake8 + py3{8,9,10,11,12}-lint: black + py3{8,9,10,11,12}-{mypy,shellcheck,lint,unit}: make skip_install = - py3{6,8,9,10,11,12}-lint: true - py3{6,8,9,10,11,12}-bandit: true + py3{8,9,10,11,12}-lint: true + py3{8,9,10,11,12}-bandit: true -[testenv:py311-pydocstyle] +[testenv:py312-pydocstyle] allowlist_externals = make commands = make diff_pydocstyle_report deps = @@ -82,7 +80,7 @@ deps = diff-cover skip_install = true -[testenv:py311-lintreadme] +[testenv:py312-lintreadme] description = Lint the README.rst->.md conversion commands = python -m build --outdir {distdir} From 70d5cd87b875823aa7983e320a165ce44d3d0a31 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Wed, 11 Oct 2023 09:38:29 +0200 Subject: [PATCH 086/165] gh-actions: codeql cancel out of date actions --- .github/workflows/codeql-analysis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8c5fc31..e759476 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -8,6 +8,10 @@ on: schedule: - cron: '0 17 * * 0' +concurrency: + group: scan-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: CodeQL-Build: From 9770ae3b628c5ca6681da379909d98833a2c6da5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 01:00:50 +0000 Subject: [PATCH 087/165] Update black requirement from ~=23.9 to ~=23.10 Updates the requirements on [black](https://github.com/psf/black) to permit the latest version. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.9.0...23.10.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index c77c4c6..789ecd2 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ diff_cover -black ~= 23.9 +black ~= 23.10 pylint pep257 pydocstyle From 774a8c465a9c3fe4de588826772d8573a7322126 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Oct 2023 00:31:06 +0000 Subject: [PATCH 088/165] Bump mypy from 1.6.0 to 1.6.1 Bumps [mypy](https://github.com/python/mypy) from 1.6.0 to 1.6.1. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.6.0...v1.6.1) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 357d788..1019b08 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.6.0 +mypy==1.6.1 types-setuptools types-requests types-PyYAML From 952d95197173cbb5f759036bb99a48bb09934797 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Tue, 31 Oct 2023 14:35:04 +0100 Subject: [PATCH 089/165] favor "path" over "location" when testing Co-authored-by: mvdbeek --- cwltest/compare.py | 28 ++++++++++++++++------------ tests/test_compare.py | 28 +++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/cwltest/compare.py b/cwltest/compare.py index f392239..18452ed 100644 --- a/cwltest/compare.py +++ b/cwltest/compare.py @@ -119,38 +119,42 @@ def _compare_location( expected: Dict[str, Any], actual: Dict[str, Any], skip_details: bool ) -> None: if "path" in expected: - comp = "path" + expected_comp = "path" if "path" not in actual: actual["path"] = actual["location"] elif "location" in expected: - comp = "location" + expected_comp = "location" else: return + if "path" in actual: + actual_comp = "path" + else: + actual_comp = "location" + path = urllib.parse.urlparse(actual[actual_comp]).path if actual.get("class") == "Directory": - actual[comp] = actual[comp].rstrip("/") + actual[actual_comp] = actual[actual_comp].rstrip("/") exist_fun: Callable[[str], bool] = os.path.isdir else: exist_fun = os.path.isfile - if "path" in actual: - path = urllib.parse.urlparse(actual["path"]).path - else: - path = urllib.parse.urlparse(actual["location"]).path if not exist_fun(path) and not skip_details: raise CompareFail.format( expected, actual, - f"{actual[comp]} does not exist", + f"{actual[actual_comp]} does not exist", ) - if expected[comp] != "Any" and ( + if expected[expected_comp] != "Any" and ( not ( - actual[comp].endswith("/" + expected[comp]) - or ("/" not in actual[comp] and expected[comp] == actual[comp]) + actual[actual_comp].endswith("/" + expected[expected_comp]) + or ( + "/" not in actual[actual_comp] + and expected[expected_comp] == actual[actual_comp] + ) ) ): raise CompareFail.format( expected, actual, - f"{actual[comp]} does not end with {expected[comp]}", + f"{actual[actual_comp]} does not end with {expected[expected_comp]}", ) diff --git a/tests/test_compare.py b/tests/test_compare.py index 6491f8d..b26c074 100644 --- a/tests/test_compare.py +++ b/tests/test_compare.py @@ -82,7 +82,7 @@ def test_compare_file_different_size(tmp_path: Path) -> None: actual = { "basename": "cores.txt", "class": "File", - "location": str(path), + "location": path.as_uri(), } with pytest.raises(CompareFail): _compare_file(expected, actual, False) @@ -102,7 +102,7 @@ def test_compare_file_different_checksum(tmp_path: Path) -> None: actual = { "basename": "cores.txt", "class": "File", - "location": str(path), + "location": path.as_uri(), } with pytest.raises(CompareFail): _compare_file(expected, actual, False) @@ -121,7 +121,7 @@ def test_compare_file_inconsistent_size(tmp_path: Path) -> None: actual = { "basename": "cores.txt", "class": "File", - "location": str(path), + "location": path.as_uri(), "size": 65535, } with pytest.raises(CompareFail): @@ -142,7 +142,7 @@ def test_compare_file_inconsistent_checksum(tmp_path: Path) -> None: "basename": "cores.txt", "checksum": "inconsistent-checksum", "class": "File", - "location": str(path), + "location": path.as_uri(), } with pytest.raises(CompareFail): _compare_file(expected, actual, False) @@ -160,7 +160,25 @@ def test_compare_directory(tmp_path: Path) -> None: actual = { "class": "Directory", - "location": str(path), + "location": path.as_uri(), + "listing": [], + } + _compare_directory(expected, actual, False) + + +def test_compare_directory_path(tmp_path: Path) -> None: + expected = { + "location": "dir", + "class": "Directory", + "listing": [], + } + + path = tmp_path / "dir" + os.makedirs(path) + + actual = { + "class": "Directory", + "path": str(path), "listing": [], } _compare_directory(expected, actual, False) From 6dd17148e8a6b3fd31e235e834764a8aae2ea337 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Tue, 31 Oct 2023 15:18:27 +0100 Subject: [PATCH 090/165] Switch to setuptools_scm --- .gitignore | 2 ++ MANIFEST.in | 2 +- Makefile | 18 ++++++++++-------- gittaggers.py | 37 ------------------------------------- setup.py | 18 +++++------------- 5 files changed, 18 insertions(+), 59 deletions(-) delete mode 100644 gittaggers.py diff --git a/.gitignore b/.gitignore index 27e2aac..613149a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ *.egg-info build dist + +cwltest/_version.py diff --git a/MANIFEST.in b/MANIFEST.in index 3aec21c..40bd4c8 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ -include Makefile gittaggers.py test-requirements.txt mypy-requirements.txt requirements.txt tox.ini mypy.ini +include Makefile test-requirements.txt mypy-requirements.txt requirements.txt tox.ini mypy.ini include dev-requirements.txt .flake8 .coveragerc release-test.sh include docs/Makefile docs/conf.py docs/requirements.txt docs/_static/favicon.ico docs/*.rst include cwltest/*.yml diff --git a/Makefile b/Makefile index 0e5889e..16b3c52 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ PYSOURCES=$(wildcard ${MODULE}/**.py tests/*.py) setup.py DEVPKGS=-rdev-requirements.txt -rtest-requirements.txt -rmypy-requirements.txt DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage pydocstyle sloccount \ python-flake8 python-mock shellcheck -VERSION=2.3.$(shell TZ=UTC git log --first-parent --max-count=1 \ +VERSION=2.4.$(shell TZ=UTC git log --first-parent --max-count=1 \ --format=format:%cd --date=format-local:%Y%m%d%H%M%S) ## all : default task (install in dev mode) @@ -105,10 +105,10 @@ codespell: ## format : check/fix all code indentation and formatting (runs black) format: $(PYSOURCES) mypy-stubs - black $^ + black --exclude cwltest/_version.py $^ format-check: $(PYSOURCES) mypy-stubs - black --diff --check $^ + black --diff --check --exclude cwltest/_version.py $^ ## pylint : run static code analysis on Python code pylint: $(PYSOURCES) @@ -151,7 +151,7 @@ test: $(PYSOURCES) ## testcov : run the cwltest test suite and collect coverage testcov: $(PYSOURCES) - python setup.py test --addopts "--cov" ${PYTEST_EXTRA} + pytest --cov ${PYTEST_EXTRA} sloccount.sc: $(PYSOURCES) Makefile sloccount --duplicates --wide --details $^ > $@ @@ -165,7 +165,7 @@ list-author-emails: @git log --format='%aN,%aE' | sort -u | grep -v 'root' mypy3: mypy -mypy: $(filter-out setup.py gittagger.py,$(PYSOURCES)) +mypy: $(filter-out setup.py,$(PYSOURCES)) MYPYPATH=$$MYPYPATH:mypy-stubs mypy $^ pyupgrade: $(filter-out schema_salad/metaschema.py,$(PYSOURCES)) @@ -176,7 +176,9 @@ release-test: FORCE git diff-index --quiet HEAD -- || ( echo You have uncommitted changes, please commit them and try again; false ) ./release-test.sh -release: release-test +release: + export SETUPTOOLS_SCM_PRETEND_VERSION=${VERSION} && \ + ./release-test.sh && \ . testenv2/bin/activate && \ pip install build && \ python -m build testenv2/src/${PACKAGE} && \ @@ -184,8 +186,8 @@ release: release-test twine upload testenv2/src/${PACKAGE}/dist/* && \ git tag ${VERSION} && git push --tags -flake8: $(PYSOURCES) - flake8 $^ +flake8: FORCE + flake8 $(PYSOURCES) FORCE: diff --git a/gittaggers.py b/gittaggers.py deleted file mode 100644 index 39e79f7..0000000 --- a/gittaggers.py +++ /dev/null @@ -1,37 +0,0 @@ -import subprocess -import time - -import pkg_resources -from setuptools.command.egg_info import egg_info - -SETUPTOOLS_VER = pkg_resources.get_distribution( - "setuptools").version.split('.') - -RECENT_SETUPTOOLS = int(SETUPTOOLS_VER[0]) > 40 or ( - int(SETUPTOOLS_VER[0]) == 40 and int(SETUPTOOLS_VER[1]) > 0) or ( - int(SETUPTOOLS_VER[0]) == 40 and int(SETUPTOOLS_VER[1]) == 0 and - int(SETUPTOOLS_VER[2]) > 0) - -class EggInfoFromGit(egg_info): - """Tag the build with git commit timestamp. - - If a build tag has already been set (e.g., "egg_info -b", building - from source package), leave it alone. - """ - - def git_timestamp_tag(self): - gitinfo = subprocess.check_output( - ['git', 'log', '--first-parent', '--max-count=1', - '--format=format:%ct', '.']).strip() - return time.strftime('.%Y%m%d%H%M%S', time.gmtime(int(gitinfo))) - - def tags(self): - if self.tag_build is None: - try: - self.tag_build = self.git_timestamp_tag() - except subprocess.CalledProcessError: - pass - return egg_info.tags(self) - - if RECENT_SETUPTOOLS: - vtags = property(tags) diff --git a/setup.py b/setup.py index 1e19380..13bd5ec 100644 --- a/setup.py +++ b/setup.py @@ -2,26 +2,18 @@ import os import pathlib import sys +from typing import List -import setuptools.command.egg_info as egg_info_cmd from setuptools import setup SETUP_DIR = os.path.dirname(__file__) README = os.path.join(SETUP_DIR, "README.rst") -try: - import gittaggers - - tagger = gittaggers.EggInfoFromGit -except ImportError: - tagger = egg_info_cmd.egg_info - needs_pytest = {"pytest", "test", "ptr"}.intersection(sys.argv) -pytest_runner = ["pytest < 8", "pytest-runner"] if needs_pytest else [] +pytest_runner: List[str] = ["pytest < 8", "pytest-runner"] if needs_pytest else [] setup( name="cwltest", - version="2.3", # update the VERSION prefix in the Makefile as well 🙂 description="Common Workflow Language testing framework", long_description=open(README).read(), long_description_content_type="text/x-rst", @@ -30,8 +22,9 @@ url="https://github.com/common-workflow-language/cwltest", download_url="https://github.com/common-workflow-language/cwltest", license="Apache 2.0", - python_requires=">=3.8, <4", - setup_requires=[] + pytest_runner, + python_requires=">=3.8,<3.13", + use_scm_version=True, + setup_requires=pytest_runner + ["setuptools_scm>=8.0.4,<9"], packages=["cwltest", "cwltest.tests"], package_dir={"cwltest.tests": "tests"}, package_data={"cwltest": ["py.typed"], "tests": ["test-data/*"]}, @@ -57,7 +50,6 @@ ], }, zip_safe=True, - cmdclass={"egg_info": tagger}, classifiers=[ "Environment :: Console", "License :: OSI Approved :: Apache Software License", From a2da92aefbbda29afe1107ed064320f9a57a87db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 00:59:44 +0000 Subject: [PATCH 091/165] Bump mypy from 1.6.1 to 1.7.0 Bumps [mypy](https://github.com/python/mypy) from 1.6.1 to 1.7.0. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.6.1...v1.7.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 1019b08..b37a768 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.6.1 +mypy==1.7.0 types-setuptools types-requests types-PyYAML From 1987ca25d76975e41974bea3a34591051ece6379 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 07:08:54 +0000 Subject: [PATCH 092/165] Update black requirement from ~=23.10 to ~=23.11 Updates the requirements on [black](https://github.com/psf/black) to permit the latest version. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.10.0...23.11.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index 789ecd2..efaf2fa 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ diff_cover -black ~= 23.10 +black ~= 23.11 pylint pep257 pydocstyle From bb3e2e116c50977cfad97cc54a4a1a04f216218a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Nov 2023 00:13:17 +0000 Subject: [PATCH 093/165] Bump mypy from 1.7.0 to 1.7.1 Bumps [mypy](https://github.com/python/mypy) from 1.7.0 to 1.7.1. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.7.0...v1.7.1) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index b37a768..988f5d4 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.7.0 +mypy==1.7.1 types-setuptools types-requests types-PyYAML From e927b1d13b39dc11da65053ce738326cbd7be2a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Nov 2023 00:30:16 +0000 Subject: [PATCH 094/165] Bump sphinx-rtd-theme from 1.3.0 to 2.0.0 Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 1.3.0 to 2.0.0. - [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst) - [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/1.3.0...2.0.0) --- updated-dependencies: - dependency-name: sphinx-rtd-theme dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index bd71cd1..1cdb96e 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ sphinx >= 2.2 -sphinx-rtd-theme==1.3.0 +sphinx-rtd-theme==2.0.0 sphinx-autoapi sphinx-autodoc-typehints typed_ast;python_version<'3.8' From 80348edd96e5bc68e9f16ca57e5caa204c08b27a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 00:30:51 +0000 Subject: [PATCH 095/165] Bump actions/setup-python from 4 to 5 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci-tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 9222ed9..08df513 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -34,7 +34,7 @@ jobs: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ env.py-semver }} cache: pip @@ -84,7 +84,7 @@ jobs: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ env.py-semver }} cache: pip @@ -114,7 +114,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.12" cache: pip From 304270098defe5d3e55dbb309a715ff1e5ff2c73 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 8 Dec 2023 15:58:05 +0100 Subject: [PATCH 096/165] remove use of deprecated pkg-resources --- cwltest/argparser.py | 13 ++++++------- cwltest/utils.py | 19 ++++++++++++------- docs/conf.py | 4 ++-- requirements.txt | 1 + tests/util.py | 17 ++++++++++++----- 5 files changed, 33 insertions(+), 21 deletions(-) diff --git a/cwltest/argparser.py b/cwltest/argparser.py index 819c553..2f7c7d9 100644 --- a/cwltest/argparser.py +++ b/cwltest/argparser.py @@ -1,8 +1,7 @@ """Command line argument parsing for cwltest.""" import argparse import sys - -import pkg_resources +from importlib.metadata import PackageNotFoundError, version from cwltest import DEFAULT_TIMEOUT @@ -107,10 +106,10 @@ def arg_parser() -> argparse.ArgumentParser: help="Create JSON badges and store them in this directory.", ) - if pkg := pkg_resources.require("cwltest"): - ver = f"{sys.argv[0]} {pkg[0].version}" - else: - ver = "{} {}".format(sys.argv[0], "unknown version") - parser.add_argument("--version", action="https://github.com/version", version=ver) + try: + ver = version("cwltest") + except PackageNotFoundError: + ver = "unknown version" + parser.add_argument("--version", action="https://github.com/version", version=f"{sys.argv[0]} {ver}") return parser diff --git a/cwltest/utils.py b/cwltest/utils.py index 60413ad..d4c0570 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -22,7 +22,6 @@ ) import junit_xml -import pkg_resources import ruamel.yaml.scanner import schema_salad.avro import schema_salad.ref_resolver @@ -32,8 +31,15 @@ from ruamel.yaml.scalarstring import ScalarString from schema_salad.exceptions import ValidationException +if sys.version_info >= (3, 9): + from importlib.resources import as_file, files +else: + from importlib_resources import as_file, files + from cwltest import REQUIRED, UNSUPPORTED_FEATURE, logger, templock +__all__ = ["files", "as_file"] + class CWLTestConfig: """Store configuration values for cwltest.""" @@ -167,12 +173,11 @@ def load_and_validate_tests(path: str) -> Tuple[Any, Dict[str, Any]]: This also processes $import directives. """ - schema_resource = pkg_resources.resource_stream(__name__, "cwltest-schema.yml") - cache: Optional[Dict[str, Union[str, Graph, bool]]] = { - "https://w3id.org/cwl/cwltest/cwltest-schema.yml": schema_resource.read().decode( - "utf-8" - ) - } + schema_resource = files("cwltest").joinpath("cwltest-schema.yml") + with schema_resource.open("r", encoding="utf-8") as fp: + cache: Optional[Dict[str, Union[str, Graph, bool]]] = { + "https://w3id.org/cwl/cwltest/cwltest-schema.yml": fp.read() + } ( document_loader, avsc_names, diff --git a/docs/conf.py b/docs/conf.py index a598182..f5a7a2e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -80,9 +80,9 @@ html_static_path = ["_static"] -from pkg_resources import get_distribution +from importlib.metadata import version as metadata_version -release = get_distribution("cwltest").version +release = metadata_version("cwltest") version = ".".join(release.split(".")[:2]) autoapi_dirs = ["../cwltest"] diff --git a/requirements.txt b/requirements.txt index bce0adf..b6c5a46 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ schema-salad >= 5.0.20200220195218, < 9 junit-xml >= 1.8 pytest >= 7, < 8 defusedxml +importlib_resources>=1.4;python_version<'3.9' diff --git a/tests/util.py b/tests/util.py index 002fa53..20cd99a 100644 --- a/tests/util.py +++ b/tests/util.py @@ -1,8 +1,12 @@ +"""Test functions.""" +import atexit import os import subprocess # nosec +from contextlib import ExitStack +from pathlib import Path from typing import List, Tuple -from pkg_resources import Requirement, ResolutionError, resource_filename +from cwltest.utils import as_file, files def get_data(filename: str) -> str: @@ -12,12 +16,15 @@ def get_data(filename: str) -> str: # joining path filepath = None try: - filepath = resource_filename(Requirement.parse("cwltest"), filename) - except ResolutionError: + file_manager = ExitStack() + atexit.register(file_manager.close) + traversable = files("cwltest") / filename + filepath = file_manager.enter_context(as_file(traversable)) + except ModuleNotFoundError: pass if not filepath or not os.path.isfile(filepath): - filepath = os.path.join(os.path.dirname(__file__), os.pardir, filename) - return filepath + filepath = Path(os.path.dirname(__file__)) / ".." / filename + return str(filepath.resolve()) def run_with_mock_cwl_runner(args: List[str]) -> Tuple[int, str, str]: From aade76aa2bd66ff4f63763e6b14dc5d35582588b Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 8 Dec 2023 17:13:24 +0100 Subject: [PATCH 097/165] cleanup --- mypy-stubs/rdflib/query.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypy-stubs/rdflib/query.pyi b/mypy-stubs/rdflib/query.pyi index 73f4008..981fe12 100644 --- a/mypy-stubs/rdflib/query.pyi +++ b/mypy-stubs/rdflib/query.pyi @@ -31,12 +31,12 @@ class Result: source: IO[Any] | None = ..., format: str | None = ..., content_type: str | None = ..., - **kwargs: Any + **kwargs: Any, ) -> Result: ... def serialize( self, destination: str | IO[Any] | None = ..., encoding: str = ..., format: str = ..., - **args: Any + **args: Any, ) -> Optional[bytes]: ... From 555a5b513bf5c6433b40d066a655309373b0d48b Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 8 Dec 2023 16:19:04 +0100 Subject: [PATCH 098/165] covert setup.py to setup.cfg Thank you https://pypi.org/project/setuptools-py2cfg/ ! --- .github/workflows/ci-tests.yml | 4 +-- Makefile | 15 ++++---- README.rst | 2 +- dev-requirements.txt | 5 +-- pyproject.toml | 9 +++++ setup.cfg | 47 +++++++++++++++++++++++- setup.py | 66 ---------------------------------- tox.ini | 4 +-- 8 files changed, 70 insertions(+), 82 deletions(-) create mode 100644 pyproject.toml delete mode 100644 setup.py diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 08df513..d52fa4f 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -46,7 +46,7 @@ jobs: - name: Upgrade setuptools and install tox run: | pip install -U pip setuptools wheel - pip install "tox<4" "tox-gh-actions<3" + pip install "tox>4,<5" "tox-gh-actions>3" - name: MyPy cache if: ${{ matrix.step == 'mypy' }} @@ -96,7 +96,7 @@ jobs: - name: Upgrade setuptools and install tox run: | pip install -U pip setuptools wheel - pip install "tox<4" "tox-gh-actions<3" + pip install "tox>4,<5" "tox-gh-actions>3" - if: ${{ matrix.step == 'pydocstyle' && github.event_name == 'pull_request'}} name: Create local branch for diff-quality for PRs diff --git a/Makefile b/Makefile index 16b3c52..c5771b5 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ PACKAGE=cwltest # `SHELL=bash` doesn't work for some, so don't use BASH-isms like # `[[` conditional expressions. -PYSOURCES=$(wildcard ${MODULE}/**.py tests/*.py) setup.py +PYSOURCES=$(wildcard ${MODULE}/**.py tests/*.py) DEVPKGS=-rdev-requirements.txt -rtest-requirements.txt -rmypy-requirements.txt DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage pydocstyle sloccount \ python-flake8 python-mock shellcheck @@ -75,7 +75,6 @@ docs: FORCE ## clean : clean up all temporary / machine-generated files clean: FORCE rm -f ${MODILE}/*.pyc tests/*.pyc - python setup.py clean --all || true rm -Rf .coverage\.* .coverage rm -f diff-cover.html @@ -93,7 +92,7 @@ pydocstyle: $(PYSOURCES) pydocstyle --add-ignore=D100,D101,D102,D103 $^ || true pydocstyle_report.txt: $(PYSOURCES) - pydocstyle setup.py $^ > $@ 2>&1 || true + pydocstyle $^ > $@ 2>&1 || true ## diff_pydocstyle_report : check Python docstring style for changed files only diff_pydocstyle_report: pydocstyle_report.txt @@ -104,11 +103,11 @@ codespell: codespell -w $(shell git ls-files | grep -v mypy-stubs | grep -v gitignore) ## format : check/fix all code indentation and formatting (runs black) -format: $(PYSOURCES) mypy-stubs - black --exclude cwltest/_version.py $^ +format: $(filter-out cwltest/_version.py,$(PYSOURCES)) mypy-stubs + black $^ -format-check: $(PYSOURCES) mypy-stubs - black --diff --check --exclude cwltest/_version.py $^ +format-check: $(filter-out cwltest/_version.py,$(PYSOURCES)) mypy-stubs + black --diff --check $^ ## pylint : run static code analysis on Python code pylint: $(PYSOURCES) @@ -165,7 +164,7 @@ list-author-emails: @git log --format='%aN,%aE' | sort -u | grep -v 'root' mypy3: mypy -mypy: $(filter-out setup.py,$(PYSOURCES)) +mypy: $(PYSOURCES) MYPYPATH=$$MYPYPATH:mypy-stubs mypy $^ pyupgrade: $(filter-out schema_salad/metaschema.py,$(PYSOURCES)) diff --git a/README.rst b/README.rst index a20438f..c4c50dd 100644 --- a/README.rst +++ b/README.rst @@ -58,7 +58,7 @@ Or from source .. code:: bash git clone https://github.com/common-workflow-language/cwltest.git - cd cwltest && python setup.py install + cd cwltest && pip install . *********************** Run on the command line diff --git a/dev-requirements.txt b/dev-requirements.txt index efaf2fa..14263d6 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -4,8 +4,8 @@ pylint pep257 pydocstyle flake8 -tox < 5 -tox-pyenv +tox >4, < 5 +virtualenv-pyenv isort wheel autoflake @@ -13,3 +13,4 @@ flake8-bugbear pyupgrade bandit auto-walrus +build diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..81d4f6e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,9 @@ +[build-system] +requires = [ + "setuptools>=45", + "setuptools_scm[toml]>=8.0.4,<9", +] +build-backend = "setuptools.build_meta" + +[tool.setuptools_scm] +write_to = "cwltest/_version.py" diff --git a/setup.cfg b/setup.cfg index cf9fe0a..d61885f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,39 @@ [aliases] -test=pytest +test = pytest + +[metadata] +name = cwltest +author = Common workflow language working group +author_email = common-workflow-language@googlegroups.com +license = Apache 2.0 +description = Common Workflow Language testing framework +url = https://github.com/common-workflow-language/cwltest +download_url = https://github.com/common-workflow-language/cwltest +long_description = file: README.rst +long_description_content_type = text/x-rst +classifiers = + Environment :: Console + License :: OSI Approved :: Apache Software License + Operating System :: POSIX + Operating System :: MacOS :: MacOS X + Development Status :: 5 - Production/Stable + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 + Typing :: Typed + +[options] +package_dir = + cwltest.tests = tests +packages = cwltest, cwltest.tests +zip_safe = True +setup_requires = setuptools_scm>=8.0.4,<9 +install_requires = file: requirements.txt +include_package_data = True +python_requires = >=3.8,<3.13 +test_suite = tests [tool:isort] multi_line_output = 3 @@ -7,3 +41,14 @@ include_trailing_comma = True force_grid_wrap = 0 use_parentheses = True line_length = 88 + +[options.entry_points] +console_scripts = cwltest=cwltest.main:main +pytest11 = cwl = cwltest.plugin [pytest-plugin] + +[options.extras_require] +pytest-plugin = pytest + +[options.package_data] +cwltest = py.typed +tests = test-data/* diff --git a/setup.py b/setup.py deleted file mode 100644 index 13bd5ec..0000000 --- a/setup.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 -import os -import pathlib -import sys -from typing import List - -from setuptools import setup - -SETUP_DIR = os.path.dirname(__file__) -README = os.path.join(SETUP_DIR, "README.rst") - -needs_pytest = {"pytest", "test", "ptr"}.intersection(sys.argv) -pytest_runner: List[str] = ["pytest < 8", "pytest-runner"] if needs_pytest else [] - -setup( - name="cwltest", - description="Common Workflow Language testing framework", - long_description=open(README).read(), - long_description_content_type="text/x-rst", - author="Common workflow language working group", - author_email="common-workflow-language@googlegroups.com", - url="https://github.com/common-workflow-language/cwltest", - download_url="https://github.com/common-workflow-language/cwltest", - license="Apache 2.0", - python_requires=">=3.8,<3.13", - use_scm_version=True, - setup_requires=pytest_runner + ["setuptools_scm>=8.0.4,<9"], - packages=["cwltest", "cwltest.tests"], - package_dir={"cwltest.tests": "tests"}, - package_data={"cwltest": ["py.typed"], "tests": ["test-data/*"]}, - include_package_data=True, - install_requires=open( - os.path.join(pathlib.Path(__file__).parent, "requirements.txt") - ) - .read() - .splitlines(), - test_suite="tests", - tests_require=open( - os.path.join(pathlib.Path(__file__).parent, "test-requirements.txt") - ) - .read() - .splitlines(), - extras_require={"pytest-plugin": ["pytest"]}, - entry_points={ - "console_scripts": [ - "cwltest=cwltest.main:main", - ], - "pytest11": [ - "cwl = cwltest.plugin [pytest-plugin]", - ], - }, - zip_safe=True, - classifiers=[ - "Environment :: Console", - "License :: OSI Approved :: Apache Software License", - "Operating System :: POSIX", - "Operating System :: MacOS :: MacOS X", - "Development Status :: 5 - Production/Stable", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Typing :: Typed", - ], -) diff --git a/tox.ini b/tox.ini index a41f0f0..3130f29 100644 --- a/tox.ini +++ b/tox.ini @@ -8,6 +8,7 @@ envlist = py312-pydocstyle skip_missing_interpreters = True +isolated_build = True [pytest] addopts = -p pytester -n auto @@ -46,13 +47,12 @@ deps = py3{8,9,10,11,12}-bandit: bandit py3{8,9,10,11,12}-mypy: -rmypy-requirements.txt -setenv = +set_env = py3{8,3,10,11,12}-unit: LC_ALL = C.UTF-8 COV_CORE_SOURCE=cwltest COV_CORE_CONFIG={toxinidir}/.coveragerc COV_CORE_DATAFILE={toxinidir}/.coverage.eager - commands = py3{8,9,10,11,12}-unit: python -m pip install -U pip setuptools wheel py3{8,9,10,11,12}-unit: python -m pytest --cov --cov-config={toxinidir}/.coveragerc --cov-append {posargs} From 7286f592f7edbb10bbb90304aec88b60986ba11d Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 8 Dec 2023 17:08:06 +0100 Subject: [PATCH 099/165] convert setup.cfg to pyproject.toml Thank you https://pypi.org/project/ini2toml/ ! --- pyproject.toml | 66 ++++++++++++++++++++++++++++++++++++++++++++++++-- setup.cfg | 54 ----------------------------------------- 2 files changed, 64 insertions(+), 56 deletions(-) delete mode 100644 setup.cfg diff --git a/pyproject.toml b/pyproject.toml index 81d4f6e..ddc54be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,71 @@ [build-system] requires = [ - "setuptools>=45", - "setuptools_scm[toml]>=8.0.4,<9", + "setuptools>=61.2", + "setuptools_scm>=8.0.4,<9", ] build-backend = "setuptools.build_meta" +[project] +name = "cwltest" +authors = [{name = "Common workflow language working group", email = "common-workflow-language@googlegroups.com"}] +license = {text = "Apache 2.0"} +description = "Common Workflow Language testing framework" +classifiers = [ + "Environment :: Console", + "Framework :: Pytest", + "License :: OSI Approved :: Apache Software License", + "Operating System :: POSIX", + "Operating System :: MacOS :: MacOS X", + "Development Status :: 5 - Production/Stable", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Typing :: Typed", +] +requires-python = ">=3.8,<3.13" +dynamic = ["version", "dependencies"] + +[project.readme] +file = "README.rst" +content-type = "text/x-rst" + +[project.urls] +Homepage = "https://github.com/common-workflow-language/cwltest" +Download = "https://github.com/common-workflow-language/cwltest" + +[project.entry-points.pytest11] +cwl = "cwltest.plugin" + +[project.optional-dependencies] +pytest-plugin = ["pytest"] + +[project.scripts] +cwltest = "cwltest.main:main" + +[tool.aliases] +test = "pytest" + +[tool.setuptools] +package-dir = {"cwltest.tests" = "tests"} +packages = ["cwltest", "cwltest.tests"] +zip-safe = true +include-package-data = true + +[tool.setuptools.package-data] +cwltest = ["py.typed"] +tests = ["test-data/*"] + +[tool.setuptools.dynamic] +dependencies = {file = ["requirements.txt"]} + +[tool.isort] +multi_line_output = "3" +include_trailing_comma = "True" +force_grid_wrap = "0" +use_parentheses = "True" +line_length = "88" + [tool.setuptools_scm] write_to = "cwltest/_version.py" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index d61885f..0000000 --- a/setup.cfg +++ /dev/null @@ -1,54 +0,0 @@ -[aliases] -test = pytest - -[metadata] -name = cwltest -author = Common workflow language working group -author_email = common-workflow-language@googlegroups.com -license = Apache 2.0 -description = Common Workflow Language testing framework -url = https://github.com/common-workflow-language/cwltest -download_url = https://github.com/common-workflow-language/cwltest -long_description = file: README.rst -long_description_content_type = text/x-rst -classifiers = - Environment :: Console - License :: OSI Approved :: Apache Software License - Operating System :: POSIX - Operating System :: MacOS :: MacOS X - Development Status :: 5 - Production/Stable - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - Programming Language :: Python :: 3.12 - Typing :: Typed - -[options] -package_dir = - cwltest.tests = tests -packages = cwltest, cwltest.tests -zip_safe = True -setup_requires = setuptools_scm>=8.0.4,<9 -install_requires = file: requirements.txt -include_package_data = True -python_requires = >=3.8,<3.13 -test_suite = tests - -[tool:isort] -multi_line_output = 3 -include_trailing_comma = True -force_grid_wrap = 0 -use_parentheses = True -line_length = 88 - -[options.entry_points] -console_scripts = cwltest=cwltest.main:main -pytest11 = cwl = cwltest.plugin [pytest-plugin] - -[options.extras_require] -pytest-plugin = pytest - -[options.package_data] -cwltest = py.typed -tests = test-data/* From 4eed3441175cf2930a23ede86887eaab002735a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 00:37:29 +0000 Subject: [PATCH 100/165] Update black requirement from ~=23.11 to ~=23.12 Updates the requirements on [black](https://github.com/psf/black) to permit the latest version. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.11.0...23.12.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index 14263d6..be07d6a 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ diff_cover -black ~= 23.11 +black ~= 23.12 pylint pep257 pydocstyle From 8d5df9b140c5b8fa98c7b362403ce269bcd01717 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Dec 2023 00:56:15 +0000 Subject: [PATCH 101/165] Bump github/codeql-action from 2 to 3 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v2...v3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e759476..47cc649 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -32,9 +32,9 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: python - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 From 8cf6bf770202b0a4377f59298ebb213ef4033271 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Dec 2023 00:43:33 +0000 Subject: [PATCH 102/165] Bump mypy from 1.7.1 to 1.8.0 Bumps [mypy](https://github.com/python/mypy) from 1.7.1 to 1.8.0. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.7.1...v1.8.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 988f5d4..a9650a3 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.7.1 +mypy==1.8.0 types-setuptools types-requests types-PyYAML From 5ed25ece7d8a816ab507b62edbc7cfc903c3c952 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 00:35:11 +0000 Subject: [PATCH 103/165] Bump actions/cache from 3 to 4 Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index d52fa4f..691a145 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -50,7 +50,7 @@ jobs: - name: MyPy cache if: ${{ matrix.step == 'mypy' }} - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: .mypy_cache/${{ env.py-semver }} key: mypy-${{ env.py-semver }} From 31712c8d34e9bb5a24b2cdef1585eb98dad498a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 00:03:45 +0000 Subject: [PATCH 104/165] Update black requirement from ~=23.12 to ~=24.1 Updates the requirements on [black](https://github.com/psf/black) to permit the latest version. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.12.0...24.1.1) --- updated-dependencies: - dependency-name: black dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index be07d6a..ef6b5ae 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ diff_cover -black ~= 23.12 +black ~= 24.1 pylint pep257 pydocstyle From dfacef5c0fa70ae67e055628eef6f7e796eaba70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:24:28 +0000 Subject: [PATCH 105/165] Update pytest requirement from <8,>=7 to >=7,<9 Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/7.0.0...8.0.0) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- test-requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index b6c5a46..16577e2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ schema-salad >= 5.0.20200220195218, < 9 junit-xml >= 1.8 -pytest >= 7, < 8 +pytest >= 7, < 9 defusedxml importlib_resources>=1.4;python_version<'3.9' diff --git a/test-requirements.txt b/test-requirements.txt index 6f0a196..c186dac 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,5 +1,5 @@ cwlref-runner cwltool -pytest >= 7, < 8 +pytest >= 7, < 9 pytest-cov pytest-xdist From 370f4778982ad55b5583a3adbdf6acfbce081793 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Mon, 29 Jan 2024 15:51:35 +0100 Subject: [PATCH 106/165] adjust types for Pytest 8.x; retaining compatability with Pytest 7.x --- cwltest/plugin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cwltest/plugin.py b/cwltest/plugin.py index 40da5f5..1a5e5b1 100644 --- a/cwltest/plugin.py +++ b/cwltest/plugin.py @@ -33,6 +33,7 @@ from _pytest.config import PytestPluginManager from _pytest.config.argparsing import Parser as PytestParser from _pytest.nodes import Node + from pluggy import HookCaller class TestRunner(Protocol): @@ -58,7 +59,7 @@ def _get_comma_separated_option(config: "Config", name: str) -> List[str]: def _run_test_hook_or_plain( test: Dict[str, str], config: utils.CWLTestConfig, - hook: TestRunner, + hook: "HookCaller", ) -> utils.TestResult: """Run tests using a provided pytest_cwl_execute_test hook or the --cwl-runner.""" processfile, jobfile = utils.prepare_test_paths(test, config.basedir) From 7493f2ea6c96199fa7fd5674f6792ddb11ce79ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 00:26:32 +0000 Subject: [PATCH 107/165] Update black requirement from ~=24.1 to ~=24.2 Updates the requirements on [black](https://github.com/psf/black) to permit the latest version. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/24.1.0...24.2.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index ef6b5ae..fc86991 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ diff_cover -black ~= 24.1 +black ~= 24.2 pylint pep257 pydocstyle From 4f6e030d532b06753da04cbb8c4fba441307224d Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Mon, 4 Mar 2024 12:20:36 +0100 Subject: [PATCH 108/165] remove deprecated LEGACY_PATH support. Pytest 8.1.0 removed support for that. No need to change our supported Pytest range, the modern pathlib.Path support has been there since Pytest 7.0 --- Makefile | 2 +- cwltest/argparser.py | 1 + cwltest/plugin.py | 6 +++--- docs/pytest.rst | 4 ++-- tests/test_prepare.py | 1 + tests/util.py | 1 + 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index c5771b5..3207ee5 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ PYSOURCES=$(wildcard ${MODULE}/**.py tests/*.py) DEVPKGS=-rdev-requirements.txt -rtest-requirements.txt -rmypy-requirements.txt DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage pydocstyle sloccount \ python-flake8 python-mock shellcheck -VERSION=2.4.$(shell TZ=UTC git log --first-parent --max-count=1 \ +VERSION=2.5.$(shell TZ=UTC git log --first-parent --max-count=1 \ --format=format:%cd --date=format-local:%Y%m%d%H%M%S) ## all : default task (install in dev mode) diff --git a/cwltest/argparser.py b/cwltest/argparser.py index 2f7c7d9..888a491 100644 --- a/cwltest/argparser.py +++ b/cwltest/argparser.py @@ -1,4 +1,5 @@ """Command line argument parsing for cwltest.""" + import argparse import sys from importlib.metadata import PackageNotFoundError, version diff --git a/cwltest/plugin.py b/cwltest/plugin.py index 1a5e5b1..75453a8 100644 --- a/cwltest/plugin.py +++ b/cwltest/plugin.py @@ -1,4 +1,5 @@ """Discovers CWL test files and converts them to pytest.Items.""" + import argparse import json import os @@ -27,7 +28,6 @@ if TYPE_CHECKING: from _pytest._code.code import ExceptionInfo, _TracebackStyle - from _pytest.compat import LEGACY_PATH from _pytest.config import Config from _pytest.config import Config as PytestConfig from _pytest.config import PytestPluginManager @@ -198,7 +198,7 @@ def repr_failure( def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str]: """Status report.""" - return self.fspath, 0, "cwl test: %s" % self.name + return self.path, 0, "cwl test: %s" % self.name class CWLYamlFile(pytest.File): @@ -342,7 +342,7 @@ def _doc_options() -> argparse.ArgumentParser: def pytest_collect_file( - file_path: Path, path: "LEGACY_PATH", parent: pytest.Collector + file_path: Path, parent: pytest.Collector ) -> Optional[pytest.Collector]: """Is this file for us.""" if ( diff --git a/docs/pytest.rst b/docs/pytest.rst index 195d392..b8d0ad9 100644 --- a/docs/pytest.rst +++ b/docs/pytest.rst @@ -2,8 +2,8 @@ Pytest plugin ************* -``cwltest`` can also be used as a Pytest plugin. The CWL test filename must -end with ``.cwltest.yml`` or ``.cwltest.yaml``. +``cwltest`` can also be used as a Pytest 7.x or 8.x plugin. The CWL test +filename must end with ``.cwltest.yml`` or ``.cwltest.yaml``. In this case, the simple command:: diff --git a/tests/test_prepare.py b/tests/test_prepare.py index 9c3c3c1..8112ef6 100644 --- a/tests/test_prepare.py +++ b/tests/test_prepare.py @@ -1,4 +1,5 @@ """Test prepare_test_command()""" + import os from cwltest import utils diff --git a/tests/util.py b/tests/util.py index 20cd99a..3c5cff3 100644 --- a/tests/util.py +++ b/tests/util.py @@ -1,4 +1,5 @@ """Test functions.""" + import atexit import os import subprocess # nosec From f43b98db755e14656be9e19e214e5b2bed5a765d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 00:40:28 +0000 Subject: [PATCH 109/165] Bump mypy from 1.8.0 to 1.9.0 Bumps [mypy](https://github.com/python/mypy) from 1.8.0 to 1.9.0. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.8.0...1.9.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index a9650a3..9eaba5e 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.8.0 +mypy==1.9.0 types-setuptools types-requests types-PyYAML From 3823ee83ed269337abcee291abe46f0ce7582266 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 00:56:06 +0000 Subject: [PATCH 110/165] Update black requirement from ~=24.2 to ~=24.4 Updates the requirements on [black](https://github.com/psf/black) to permit the latest version. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/24.2.0...24.4.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index fc86991..4280a59 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ diff_cover -black ~= 24.2 +black ~= 24.4 pylint pep257 pydocstyle From e36af9ec018701bf0cfb4b91c8cace48dbe9d14d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 00:53:24 +0000 Subject: [PATCH 111/165] Bump mypy from 1.9.0 to 1.10.0 Bumps [mypy](https://github.com/python/mypy) from 1.9.0 to 1.10.0. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/1.9.0...v1.10.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 9eaba5e..fbaccfc 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.9.0 +mypy==1.10.0 types-setuptools types-requests types-PyYAML From 01a82353195e8e7ccd88f616ef5629b3369f17c6 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Thu, 25 Apr 2024 13:45:43 +0300 Subject: [PATCH 112/165] mark this editing of a mutable while looping as okay --- cwltest/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cwltest/main.py b/cwltest/main.py index f93a279..321a9b1 100644 --- a/cwltest/main.py +++ b/cwltest/main.py @@ -132,7 +132,7 @@ def main() -> int: for t in tests: if t.get("label"): logger.warning("The `label` field is deprecated. Use `id` field instead.") - t["short_name"] = t["label"] + t["short_name"] = t["label"] # noqa: B909 elif t.get("id"): if isinstance(t.get("id"), str): t["short_name"] = utils.shortname(t["id"]) From 2eb15377fc5829761e1efb0d6cc66f163ba144aa Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Thu, 25 Apr 2024 13:49:01 +0300 Subject: [PATCH 113/165] mypy: simplify configuration --- mypy.ini | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/mypy.ini b/mypy.ini index 6a442f8..11917ac 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,24 +1,10 @@ [mypy] +strict = True show_error_context = true show_column_numbers = true show_error_codes = true pretty = true - -# --strict options as of mypy 0.910 -warn_unused_configs = True -disallow_any_generics = True -disallow_subclassing_any = True -disallow_untyped_calls = True -disallow_untyped_defs = True -disallow_incomplete_defs = True -check_untyped_defs = True -disallow_untyped_decorators = True -no_implicit_optional = True -warn_redundant_casts = True -warn_unused_ignores = True -warn_return_any = True -implicit_reexport = False -strict_equality = True +warn_unreachable = True [mypy-ruamel.*] ignore_errors = True From 7266ad44c871524c5ac9e4b0934b5014d001f5d4 Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Sat, 13 Apr 2024 09:04:37 +0000 Subject: [PATCH 114/165] Handling invalid output object from engines --- cwltest/utils.py | 17 +++++++++++++++++ tests/test-data/dummy-executor.sh | 3 +++ tests/test-data/empty.yml | 1 + tests/test-data/nothing.yml | 10 ++++++++++ tests/test-data/true.cwl | 5 +++++ tests/test_invalid_outputs.py | 17 +++++++++++++++++ tests/util.py | 9 ++++++--- 7 files changed, 59 insertions(+), 3 deletions(-) create mode 100755 tests/test-data/dummy-executor.sh create mode 100644 tests/test-data/empty.yml create mode 100644 tests/test-data/nothing.yml create mode 100644 tests/test-data/true.cwl create mode 100644 tests/test_invalid_outputs.py diff --git a/cwltest/utils.py b/cwltest/utils.py index d4c0570..012e286 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -422,6 +422,23 @@ def run_test_plain( " ".join([shlex.quote(tc) for tc in test_command]), ) raise + except json.JSONDecodeError: + logger.error( + """Test %s failed: %s""", + number, + " ".join([shlex.quote(tc) for tc in test_command]), + ) + logger.error(test.get("doc", "").replace("\n", " ").strip()) + invalid_json_msg = "Output is not a valid JSON document: '%s'" % outstr + logger.error(invalid_json_msg) + return TestResult( + 1, + outstr, + outerr, + duration, + config.classname, + invalid_json_msg, + ) except subprocess.TimeoutExpired: logger.error( """Test %s timed out: %s""", diff --git a/tests/test-data/dummy-executor.sh b/tests/test-data/dummy-executor.sh new file mode 100755 index 0000000..ca3a674 --- /dev/null +++ b/tests/test-data/dummy-executor.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +echo "it is not JSON format!" diff --git a/tests/test-data/empty.yml b/tests/test-data/empty.yml new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/tests/test-data/empty.yml @@ -0,0 +1 @@ +{} diff --git a/tests/test-data/nothing.yml b/tests/test-data/nothing.yml new file mode 100644 index 0000000..1e860a7 --- /dev/null +++ b/tests/test-data/nothing.yml @@ -0,0 +1,10 @@ +- job: empty.yml + tool: true.cwl + output: {} + id: do_nothing + doc: Example of doing nothing +- job: empty.yml + tool: true.cwl + output: {} + id: do_nothing2 + doc: Example of doing nothing more diff --git a/tests/test-data/true.cwl b/tests/test-data/true.cwl new file mode 100644 index 0000000..f8e5e7a --- /dev/null +++ b/tests/test-data/true.cwl @@ -0,0 +1,5 @@ +class: CommandLineTool +cwlVersion: v1.0 +inputs: {} +outputs: {} +baseCommand: ["true"] diff --git a/tests/test_invalid_outputs.py b/tests/test_invalid_outputs.py new file mode 100644 index 0000000..d57182d --- /dev/null +++ b/tests/test_invalid_outputs.py @@ -0,0 +1,17 @@ +from pathlib import Path + +import schema_salad.ref_resolver + +from .util import get_data, run_with_mock_cwl_runner + + +def test_invalid_outputs(tmp_path: Path) -> None: + args = [ + "--test", + schema_salad.ref_resolver.file_uri(get_data("tests/test-data/nothing.yml")), + ] + error_code, stdout, stderr = run_with_mock_cwl_runner( + args, get_data("tests/test-data/dummy-executor.sh") + ) + assert error_code == 1 + assert "0 tests passed, 2 failures, 0 unsupported features" in stderr diff --git a/tests/util.py b/tests/util.py index 3c5cff3..9394612 100644 --- a/tests/util.py +++ b/tests/util.py @@ -5,7 +5,7 @@ import subprocess # nosec from contextlib import ExitStack from pathlib import Path -from typing import List, Tuple +from typing import List, Optional, Tuple from cwltest.utils import as_file, files @@ -28,9 +28,12 @@ def get_data(filename: str) -> str: return str(filepath.resolve()) -def run_with_mock_cwl_runner(args: List[str]) -> Tuple[int, str, str]: +def run_with_mock_cwl_runner( + args: List[str], cwl_runner: Optional[str] = None +) -> Tuple[int, str, str]: """Bind a mock cwlref-runner implementation to cwltest.""" - cwl_runner = get_data("tests/test-data/mock_cwl_runner.py") + if cwl_runner is None: + cwl_runner = get_data("tests/test-data/mock_cwl_runner.py") process = subprocess.Popen( # nosec ["cwltest", "--tool", cwl_runner] + args, stdout=subprocess.PIPE, From 2b1ac8081006af630a701a0cf1f16828616ef569 Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Fri, 17 May 2024 13:02:15 +0200 Subject: [PATCH 115/165] Generate markdown reports to badgedir for each tag --- .flake8 | 2 + cwltest/argparser.py | 3 + cwltest/main.py | 18 +- cwltest/plugin.py | 50 ++++- cwltest/utils.py | 188 ++++++++++++++++-- tests/test-data/badgedir.yaml | 38 ++++ .../conformance_test_v1.2.cwltest.yaml | 8 +- tests/test-data/mock_cwl_runner.py | 2 +- .../test-data/v1.0/null-expression2-tool.cwl | 14 ++ tests/test_badgedir.py | 98 +++++++++ tests/test_plugin.py | 3 +- 11 files changed, 394 insertions(+), 30 deletions(-) create mode 100644 tests/test-data/badgedir.yaml create mode 100644 tests/test-data/v1.0/null-expression2-tool.cwl create mode 100644 tests/test_badgedir.py diff --git a/.flake8 b/.flake8 index ed7277f..60ef4d0 100644 --- a/.flake8 +++ b/.flake8 @@ -5,3 +5,5 @@ select = B,C,E,F,W,T4 extend-ignore = E501,B905 # when Python 3.10 is the minimum version, re-enable check B905 for zip + strict extend-select = B9 +per-file-ignores= + ./tests/test_badgedir.py:B950 diff --git a/cwltest/argparser.py b/cwltest/argparser.py index 888a491..1d2458c 100644 --- a/cwltest/argparser.py +++ b/cwltest/argparser.py @@ -18,6 +18,9 @@ def arg_parser() -> argparse.ArgumentParser: parser.add_argument( "--basedir", type=str, help="Basedir to use for tests", default="." ) + parser.add_argument( + "--baseuri", type=str, help="Base URI to use links in the report", default=None + ) parser.add_argument("-l", action="https://github.com/store_true", help="List tests then exit") parser.add_argument( "-n", type=str, default=None, help="Run specific tests, format is 1,3-6,9" diff --git a/cwltest/main.py b/cwltest/main.py index 321a9b1..4909c89 100644 --- a/cwltest/main.py +++ b/cwltest/main.py @@ -13,7 +13,7 @@ import schema_salad.ref_resolver import schema_salad.schema from cwltest.argparser import arg_parser -from cwltest.utils import CWLTestConfig, TestResult +from cwltest.utils import CWLTestConfig, CWLTestReport, TestResult from schema_salad.exceptions import ValidationException from cwltest import logger, utils @@ -58,7 +58,11 @@ def _run_test( sys.stderr.flush() config = CWLTestConfig( basedir=args.basedir, + test_baseuri=args.baseuri, + test_basedir=args.test_basedir, classname=args.classname, + entry=args.test, + entry_line=test["line"], tool=args.tool, args=args.args, testargs=args.testargs, @@ -96,6 +100,12 @@ def main() -> int: arg_parser().print_help() return 1 + args.test_basedir = os.path.dirname(utils.absuri(args.test)) + "/" + if args.baseuri is None: + args.baseuri = "file://" + args.test_basedir + if not args.baseuri.endswith("/"): + args.baseuri = args.baseuri + "/" + try: tests, metadata = utils.load_and_validate_tests(args.test) except ValidationException: @@ -106,8 +116,8 @@ def main() -> int: suite_name, _ = os.path.splitext(os.path.basename(args.test)) report: Optional[junit_xml.TestSuite] = junit_xml.TestSuite(suite_name, []) - ntotal = defaultdict(int) # type: Dict[str, int] - npassed = defaultdict(int) # type: Dict[str, int] + ntotal: Dict[str, int] = defaultdict(int) + npassed: Dict[str, List[CWLTestReport]] = defaultdict(list) if args.only_tools: alltests = tests @@ -233,7 +243,7 @@ def main() -> int: junit_xml.to_xml_report_file(xml, [cast(junit_xml.TestSuite, report)]) if args.badgedir: - utils.generate_badges(args.badgedir, ntotal, npassed) + utils.generate_badges(args.badgedir, ntotal, npassed, nfailures, nunsupported) if failures == 0 and unsupported == 0: logger.info("All tests passed") diff --git a/cwltest/plugin.py b/cwltest/plugin.py index 75453a8..baa4cae 100644 --- a/cwltest/plugin.py +++ b/cwltest/plugin.py @@ -20,6 +20,7 @@ Union, cast, ) +from urllib.parse import urljoin import pytest from cwltest.compare import CompareFail, compare @@ -64,6 +65,13 @@ def _run_test_hook_or_plain( """Run tests using a provided pytest_cwl_execute_test hook or the --cwl-runner.""" processfile, jobfile = utils.prepare_test_paths(test, config.basedir) start_time = time.time() + reltool = os.path.relpath(test["tool"], start=config.test_basedir) + tooluri = urljoin(config.test_baseuri, reltool) + if "job" in test: + reljob = os.path.relpath(test["job"], start=config.test_basedir) + joburi = urljoin(config.test_baseuri, reljob) + else: + joburi = None outerr = "" hook_out = hook(config=config, processfile=processfile, jobfile=jobfile) if not hook_out: @@ -74,7 +82,14 @@ def _run_test_hook_or_plain( if returncode == UNSUPPORTED_FEATURE: if REQUIRED not in test.get("tags", ["required"]): return utils.TestResult( - UNSUPPORTED_FEATURE, outstr, "", duration, config.classname + UNSUPPORTED_FEATURE, + outstr, + "", + duration, + config.classname, + config.entry, + tooluri, + joburi, ) elif returncode != 0: if not bool(test.get("should_fail", False)): @@ -82,9 +97,26 @@ def _run_test_hook_or_plain( logger.warning(test.get("doc")) message = "Returned non-zero but it should be zero" return utils.TestResult( - 1, outstr, outerr, duration, config.classname, message + 1, + outstr, + outerr, + duration, + config.classname, + config.entry, + tooluri, + joburi, + message, ) - return utils.TestResult(0, outstr, outerr, duration, config.classname) + return utils.TestResult( + 0, + outstr, + outerr, + duration, + config.classname, + config.entry, + tooluri, + joburi, + ) if bool(test.get("should_fail", False)): return utils.TestResult( 1, @@ -92,6 +124,9 @@ def _run_test_hook_or_plain( outerr, duration, config.classname, + config.entry, + tooluri, + joburi, "Test should failed, but it did not.", ) @@ -111,6 +146,9 @@ def _run_test_hook_or_plain( outerr, duration, config.classname, + config.entry, + tooluri, + joburi, fail_message, ) @@ -137,6 +175,10 @@ def runtest(self) -> None: cwl_args = self.config.getoption("cwl_args") config = utils.CWLTestConfig( basedir=self.config.getoption("cwl_basedir"), + test_baseuri=self.config.getoption("cwl_basedir"), + test_basedir=self.config.getoption("cwl_basedir"), + entry="tests.yaml", + entry_line="0", outdir=str( self.config._tmp_path_factory.mktemp( # type: ignore[attr-defined] self.spec.get("label", "unlabled_test") @@ -382,7 +424,7 @@ def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None: _, ) = utils.parse_results(results, tests) if cwl_badgedir := session.config.getoption("cwl_badgedir"): - utils.generate_badges(cwl_badgedir, ntotal, npassed) + utils.generate_badges(cwl_badgedir, ntotal, npassed, nfailures, nunsupported) def pytest_addhooks(pluginmanager: "PytestPluginManager") -> None: diff --git a/cwltest/utils.py b/cwltest/utils.py index 012e286..c9ef724 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -20,6 +20,7 @@ Union, cast, ) +from urllib.parse import urljoin import junit_xml import ruamel.yaml.scanner @@ -46,7 +47,11 @@ class CWLTestConfig: def __init__( self, + entry: str, + entry_line: str, basedir: Optional[str] = None, + test_baseuri: Optional[str] = None, + test_basedir: Optional[str] = None, outdir: Optional[str] = None, classname: Optional[str] = None, tool: Optional[str] = None, @@ -58,8 +63,13 @@ def __init__( ) -> None: """Initialize test configuration.""" self.basedir: str = basedir or os.getcwd() + self.test_baseuri: str = test_baseuri or "file://" + self.basedir + self.test_basedir: str = test_basedir or self.basedir self.outdir: Optional[str] = outdir self.classname: str = classname or "" + self.entry = urljoin( + self.test_baseuri, os.path.basename(entry) + f"#L{entry_line}" + ) self.tool: str = tool or "cwl-runner" self.args: List[str] = args or [] self.testargs: List[str] = testargs or [] @@ -68,6 +78,20 @@ def __init__( self.runner_quiet: bool = runner_quiet or True +class CWLTestReport: + """Encapsulate relevant test result data for a markdown report.""" + + def __init__( + self, id: str, category: List[str], entry: str, tool: str, job: Optional[str] + ) -> None: + """Initialize a CWLTestReport object.""" + self.id = id + self.category = category + self.entry = entry + self.tool = tool + self.job = job + + class TestResult: """Encapsulate relevant test result data.""" @@ -78,6 +102,9 @@ def __init__( error_output: str, duration: float, classname: str, + entry: str, + tool: str, + job: Optional[str], message: str = "", ) -> None: """Initialize a TestResult object.""" @@ -87,6 +114,9 @@ def __init__( self.duration = duration self.message = message self.classname = classname + self.entry = entry + self.tool = tool + self.job = job def create_test_case(self, test: Dict[str, Any]) -> junit_xml.TestCase: """Create a jUnit XML test case from this test result.""" @@ -108,6 +138,25 @@ def create_test_case(self, test: Dict[str, Any]) -> junit_xml.TestCase: case.failure_message = self.message return case + def create_report_entry(self, test: Dict[str, Any]) -> CWLTestReport: + return CWLTestReport( + test.get("id", "no-id"), + test.get("tags", ["required"]), + self.entry, + self.tool, + self.job, + ) + + +def _clean_ruamel_list(obj: List[Any]) -> Any: + """Entrypoint to transform roundtrip loaded ruamel.yaml to plain objects.""" + new_list = [] + for entry in obj: + e: Any = _clean_ruamel(entry) + e["line"] = str(entry.lc.line) + new_list.append(e) + return new_list + def _clean_ruamel(obj: Any) -> Any: """Transform roundtrip loaded ruamel.yaml to plain objects.""" @@ -132,13 +181,17 @@ def _clean_ruamel(obj: Any) -> Any: def generate_badges( - badgedir: str, ntotal: Dict[str, int], npassed: Dict[str, int] + badgedir: str, + ntotal: Dict[str, int], + npassed: Dict[str, List[CWLTestReport]], + nfailures: Dict[str, List[CWLTestReport]], + nunsupported: Dict[str, List[CWLTestReport]], ) -> None: """Generate badges with conformance levels.""" os.mkdir(badgedir) for t, v in ntotal.items(): - percent = int((npassed[t] / float(v)) * 100) - if npassed[t] == v: + percent = int((len(npassed[t]) / float(v)) * 100) + if len(npassed[t]) == v: color = "green" elif t == "required": color = "red" @@ -156,6 +209,42 @@ def generate_badges( ) ) + with open(f"{badgedir}/{t}.md", "w") as out: + print(f"# `{t}` tests", file=out) + + print("## List of passed tests", file=out) + for e in npassed[t]: + base = f"[{shortname(e.id)}]({e.entry})" + tool = f"[tool]({e.tool})" + if e.job: + arr = [tool, f"[job]({e.job})"] + else: + arr = [tool] + args = ", ".join(arr) + print(f"- {base} ({args})", file=out) + + print("## List of failed tests", file=out) + for e in nfailures[t]: + base = f"[{shortname(e.id)}]({e.entry})" + tool = f"[tool]({e.tool})" + if e.job: + arr = [tool, f"[job]({e.job})"] + else: + arr = [tool] + args = ", ".join(arr) + print(f"- {base} ({args})", file=out) + + print("## List of unsupported tests", file=out) + for e in nunsupported[t]: + base = f"[{shortname(e.id)}]({e.entry})" + tool = f"[tool]({e.tool})" + if e.job: + arr = [tool, f"[job]({e.job})"] + else: + arr = [tool] + args = ", ".join(arr) + print(f"- {base} ({args})", file=out) + def get_test_number_by_key( tests: List[Dict[str, str]], key: str, value: str @@ -194,7 +283,7 @@ def load_and_validate_tests(path: str) -> Tuple[Any, Dict[str, Any]]: tests, metadata = schema_salad.schema.load_and_validate( document_loader, avsc_names, path, True ) - tests = cast(List[Dict[str, Any]], _clean_ruamel(tests)) + tests = cast(List[Dict[str, Any]], _clean_ruamel_list(tests)) return tests, metadata @@ -209,10 +298,10 @@ def parse_results( int, # passed int, # failures int, # unsupported - Dict[str, int], - Dict[str, int], - Dict[str, int], - Dict[str, int], + Dict[str, int], # total for each tag + Dict[str, List[CWLTestReport]], # passed for each tag + Dict[str, List[CWLTestReport]], # failures for each tag + Dict[str, List[CWLTestReport]], # unsupported for each tag Optional[junit_xml.TestSuite], ]: """ @@ -226,12 +315,13 @@ def parse_results( failures = 0 unsupported = 0 ntotal: Dict[str, int] = defaultdict(int) - nfailures: Dict[str, int] = defaultdict(int) - nunsupported: Dict[str, int] = defaultdict(int) - npassed: Dict[str, int] = defaultdict(int) + nfailures: Dict[str, List[CWLTestReport]] = defaultdict(list) + nunsupported: Dict[str, List[CWLTestReport]] = defaultdict(list) + npassed: Dict[str, List[CWLTestReport]] = defaultdict(list) for i, test_result in enumerate(results): test_case = test_result.create_test_case(tests[i]) + test_report = test_result.create_report_entry(tests[i]) test_case.url = ( f"cwltest:{suite_name}#{i + 1}" if suite_name is not None @@ -247,21 +337,21 @@ def parse_results( if return_code == 0: passed += 1 for t in tags: - npassed[t] += 1 + npassed[t].append(test_report) elif return_code != 0 and return_code != UNSUPPORTED_FEATURE: failures += 1 for t in tags: - nfailures[t] += 1 + nfailures[t].append(test_report) test_case.add_failure_info(output=test_result.message) elif return_code == UNSUPPORTED_FEATURE and category == REQUIRED: failures += 1 for t in tags: - nfailures[t] += 1 + nfailures[t].append(test_report) test_case.add_failure_info(output=test_result.message) elif category != REQUIRED and return_code == UNSUPPORTED_FEATURE: unsupported += 1 for t in tags: - nunsupported[t] += 1 + nunsupported[t].append(test_report) test_case.add_skipped_info("Unsupported") else: raise Exception( @@ -352,6 +442,15 @@ def run_test_plain( test_command: List[str] = [] duration = 0.0 number = "?" + + reltool = os.path.relpath(test["tool"], start=config.test_basedir) + tooluri = urljoin(config.test_baseuri, reltool) + if "job" in test: + reljob = os.path.relpath(test["job"], start=config.test_basedir) + joburi = urljoin(config.test_baseuri, reljob) + else: + joburi = None + if test_number is not None: number = str(test_number) process: Optional[subprocess.Popen[str]] = None @@ -385,10 +484,26 @@ def run_test_plain( "tags", ["required"] ): return TestResult( - UNSUPPORTED_FEATURE, outstr, outerr, duration, config.classname + UNSUPPORTED_FEATURE, + outstr, + outerr, + duration, + config.classname, + config.entry, + tooluri, + joburi, ) if test.get("should_fail", False): - return TestResult(0, outstr, outerr, duration, config.classname) + return TestResult( + 0, + outstr, + outerr, + duration, + config.classname, + config.entry, + tooluri, + joburi, + ) if test_number: logger.error( """Test %i failed: %s""", @@ -405,7 +520,17 @@ def run_test_plain( logger.error("Does not support required feature") else: logger.error("Returned non-zero") - return TestResult(1, outstr, outerr, duration, config.classname, str(err)) + return TestResult( + 1, + outstr, + outerr, + duration, + config.classname, + config.entry, + tooluri, + joburi, + str(err), + ) except (ruamel.yaml.scanner.ScannerError, TypeError) as err: logger.error( """Test %s failed: %s""", @@ -437,6 +562,9 @@ def run_test_plain( outerr, duration, config.classname, + config.entry, + tooluri, + joburi, invalid_json_msg, ) except subprocess.TimeoutExpired: @@ -457,6 +585,9 @@ def run_test_plain( outerr, float(cast(int, config.timeout)), config.classname, + config.entry, + tooluri, + joburi, "Test timed out", ) finally: @@ -480,7 +611,16 @@ def run_test_plain( ) logger.warning(test.get("doc", "").replace("\n", " ").strip()) logger.warning("Returned zero but it should be non-zero") - return TestResult(1, outstr, outerr, duration, config.classname) + return TestResult( + 1, + outstr, + outerr, + duration, + config.classname, + config.entry, + tooluri, + joburi, + ) try: compare(test.get("output"), out) @@ -503,6 +643,9 @@ def run_test_plain( outerr, duration, config.classname, + config.entry, + tooluri, + joburi, fail_message, ) @@ -514,3 +657,10 @@ def shortname(name: str) -> str: It is a workaround of https://github.com/common-workflow-language/schema_salad/issues/511. """ return [n for n in re.split("[/#]", name) if len(n)][-1] + + +def absuri(path: str) -> str: + """Return an absolute URI.""" + if "://" in path: + return path + return "file://" + os.path.abspath(path) diff --git a/tests/test-data/badgedir.yaml b/tests/test-data/badgedir.yaml new file mode 100644 index 0000000..80bd1bd --- /dev/null +++ b/tests/test-data/badgedir.yaml @@ -0,0 +1,38 @@ +- output: {} + job: empty.yml + tool: return-0.cwl + id: success_w_job + doc: Successful test with a job file + tags: [ command_line_tool ] + +- output: {} + tool: return-0.cwl + id: success_wo_job + doc: Successful test without a job file + tags: [ command_line_tool ] + +- output: {} + job: empty.yml + tool: return-1.cwl + id: failure_w_job + doc: Failed test with a job file + tags: [ command_line_tool ] + +- output: {} + tool: return-1.cwl + id: failure_wo_job + doc: Failed test without a job file + tags: [ command_line_tool ] + +- output: {} + job: empty.yml + tool: return-unsupported.cwl + id: unsupported_w_job + doc: Unsupported test with a job file + tags: [ command_line_tool ] + +- output: {} + tool: return-unsupported.cwl + id: unsupported_wo_job + doc: Unsupported test without a job file + tags: [ command_line_tool ] diff --git a/tests/test-data/conformance_test_v1.2.cwltest.yaml b/tests/test-data/conformance_test_v1.2.cwltest.yaml index 0b78da9..3f7a605 100644 --- a/tests/test-data/conformance_test_v1.2.cwltest.yaml +++ b/tests/test-data/conformance_test_v1.2.cwltest.yaml @@ -12,4 +12,10 @@ tool: v1.0/cat1-testcli.cwl id: cl_optional_bindings_provided doc: Test command line with optional input (provided) - tags: [ command_line_tool ] \ No newline at end of file + tags: [ command_line_tool ] + +- tool: v1.0/null-expression2-tool.cwl + should_fail: true + id: expression_any_nodefaultany + doc: Test Any without defaults cannot be unspecified. + tags: [ required, inline_javascript, expression_tool ] diff --git a/tests/test-data/mock_cwl_runner.py b/tests/test-data/mock_cwl_runner.py index d807203..98d668e 100755 --- a/tests/test-data/mock_cwl_runner.py +++ b/tests/test-data/mock_cwl_runner.py @@ -15,7 +15,7 @@ def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("processfile") - parser.add_argument("jobfile") + parser.add_argument("jobfile", nargs='?', default=None) parser.add_argument("--version", action="https://github.com/version", version="%(prog)s 1.0") parser.add_argument("--outdir") parser.add_argument("--quiet", action="https://github.com/store_true") diff --git a/tests/test-data/v1.0/null-expression2-tool.cwl b/tests/test-data/v1.0/null-expression2-tool.cwl new file mode 100644 index 0000000..2b09ec0 --- /dev/null +++ b/tests/test-data/v1.0/null-expression2-tool.cwl @@ -0,0 +1,14 @@ +#!/usr/bin/env cwl-runner + +class: ExpressionTool +requirements: + - class: InlineJavascriptRequirement +cwlVersion: v1.2 + +inputs: + i1: Any + +outputs: + output: int + +expression: "$({'output': (inputs.i1 == 'the-default' ? 1 : 2)})" \ No newline at end of file diff --git a/tests/test_badgedir.py b/tests/test_badgedir.py new file mode 100644 index 0000000..cf2f3ac --- /dev/null +++ b/tests/test_badgedir.py @@ -0,0 +1,98 @@ +import os +import json +from pathlib import Path +from textwrap import dedent + +import schema_salad.ref_resolver + +from .util import get_data, run_with_mock_cwl_runner + + +def test_badgedir(tmp_path: Path) -> None: + badgedir = tmp_path / "badgedir" + + args = [ + "--test", + schema_salad.ref_resolver.file_uri( + get_data("tests/test-data/conformance_test_v1.2.cwltest.yaml") + ), + "--badgedir", + str(badgedir), + ] + cwd = os.getcwd() + try: + os.chdir(get_data("tests/test-data/")) + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + finally: + os.chdir(cwd) + + assert error_code == 1 + required_json = badgedir / "required.json" + assert required_json.exists() + with open(required_json) as file: + obj = json.load(file) + assert obj.get("subject", "") == "required" + assert obj.get("status", "") == "0%" + assert obj.get("color", "") == "red" + + required_md = badgedir / "required.md" + assert required_md.exists() + with open(required_md) as file: + s = file.read() + assert "file://" in s + assert "tests/test-data/conformance_test_v1.2.cwltest.yaml" in s + assert "v1.0/cat-job.json" in s + assert "v1.0/cat1-testcli.cwl" in s + + clt = badgedir / "command_line_tool.json" + assert clt.exists() + with open(clt) as file: + obj = json.load(file) + assert obj.get("subject", "") == "command_line_tool" + assert obj.get("status", "") == "0%" + assert obj.get("color", "") == "yellow" + assert (badgedir / "command_line_tool.md").exists() + + +def test_badgedir_report_with_baseuri(tmp_path: Path) -> None: + badgedir = tmp_path / "badgedir" + + baseuri = "https://example.com/specified/uri" + + args = [ + "--test", + schema_salad.ref_resolver.file_uri(get_data("tests/test-data/badgedir.yaml")), + "--badgedir", + str(badgedir), + "--baseuri", + baseuri, + ] + cwd = os.getcwd() + try: + os.chdir(get_data("tests/test-data/")) + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + finally: + os.chdir(cwd) + + clt_md = badgedir / "command_line_tool.md" + assert clt_md.exists() + with open(clt_md) as file: + contents = file.read() + assert contents == markdown_report_with(baseuri) + + +def markdown_report_with(baseuri: str) -> str: + return dedent( + f""" + # `command_line_tool` tests + ## List of passed tests + - [success_w_job]({baseuri}/badgedir.yaml#L0) ([tool]({baseuri}/return-0.cwl), [job]({baseuri}/empty.yml)) + - [success_wo_job]({baseuri}/badgedir.yaml#L7) ([tool]({baseuri}/return-0.cwl)) + ## List of failed tests + - [failure_w_job]({baseuri}/badgedir.yaml#L13) ([tool]({baseuri}/return-1.cwl), [job]({baseuri}/empty.yml)) + - [failure_wo_job]({baseuri}/badgedir.yaml#L20) ([tool]({baseuri}/return-1.cwl)) + ## List of unsupported tests + - [unsupported_w_job]({baseuri}/badgedir.yaml#L26) ([tool]({baseuri}/return-unsupported.cwl), [job]({baseuri}/empty.yml)) + - [unsupported_wo_job]({baseuri}/badgedir.yaml#L33) ([tool]({baseuri}/return-unsupported.cwl)) + """ + )[1:] diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 4951c3f..4bc4a69 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -13,6 +13,7 @@ def _load_v1_0_dir(path: Path) -> None: inner_dir = os.path.join(path.parent, "v1.0") os.mkdir(inner_dir) shutil.copy(get_data("tests/test-data/v1.0/cat1-testcli.cwl"), inner_dir) + shutil.copy(get_data("tests/test-data/v1.0/null-expression2-tool.cwl"), inner_dir) shutil.copy(get_data("tests/test-data/v1.0/cat-job.json"), inner_dir) shutil.copy(get_data("tests/test-data/v1.0/cat-n-job.json"), inner_dir) shutil.copy(get_data("tests/test-data/v1.0/hello.txt"), inner_dir) @@ -104,7 +105,7 @@ def test_no_label(pytester: "Pytester") -> None: result = pytester.runpytest( "-k", "conformance_test_v1.2.cwltest.yaml", "--cwl-tags", "required" ) - result.assert_outcomes(passed=1, skipped=1) + result.assert_outcomes(passed=2, skipped=1) def test_cwltool_hook(pytester: "Pytester") -> None: From dd269f36d182786322b668a80b61c736887325f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 00:38:59 +0000 Subject: [PATCH 116/165] Bump mypy from 1.10.0 to 1.10.1 Bumps [mypy](https://github.com/python/mypy) from 1.10.0 to 1.10.1. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.10.0...v1.10.1) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index fbaccfc..43adedd 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.10.0 +mypy==1.10.1 types-setuptools types-requests types-PyYAML From c3a268f044004eed32ac0ab5f574d6d6a3e96cff Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Wed, 26 Jun 2024 11:10:25 +0900 Subject: [PATCH 117/165] Replace `{distdir}` with `dist` --- tox.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 3130f29..f036283 100644 --- a/tox.ini +++ b/tox.ini @@ -83,8 +83,8 @@ skip_install = true [testenv:py312-lintreadme] description = Lint the README.rst->.md conversion commands = - python -m build --outdir {distdir} - twine check {distdir}/* + python -m build --outdir dist + twine check dist/* deps = twine build From 8b81c1f020c03168e61cc89f4906b39bd0068f9d Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Thu, 27 Jun 2024 17:05:10 +0900 Subject: [PATCH 118/165] Fix .gitignore --- .gitignore | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.gitignore b/.gitignore index 613149a..dbcde96 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,12 @@ build dist cwltest/_version.py + +# Generated by tox +coverage.xml +.coverage +.coverage.* +pydocstyle_report.txt + +# Generated by `make release-test` +testenv* From 06b640ef3ead80271f428b56e0f9d656a41897ee Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Tue, 9 Jul 2024 03:58:01 +0000 Subject: [PATCH 119/165] Remove redundant code --- cwltest/utils.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cwltest/utils.py b/cwltest/utils.py index c9ef724..d2fa57e 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -343,11 +343,6 @@ def parse_results( for t in tags: nfailures[t].append(test_report) test_case.add_failure_info(output=test_result.message) - elif return_code == UNSUPPORTED_FEATURE and category == REQUIRED: - failures += 1 - for t in tags: - nfailures[t].append(test_report) - test_case.add_failure_info(output=test_result.message) elif category != REQUIRED and return_code == UNSUPPORTED_FEATURE: unsupported += 1 for t in tags: From 12a0f7c849933d0f22a12bd51502bb4988ab12e5 Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Tue, 9 Jul 2024 10:34:42 +0000 Subject: [PATCH 120/165] Always use lightweight tags for releases --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3207ee5..097ccc6 100644 --- a/Makefile +++ b/Makefile @@ -183,7 +183,7 @@ release: python -m build testenv2/src/${PACKAGE} && \ pip install twine && \ twine upload testenv2/src/${PACKAGE}/dist/* && \ - git tag ${VERSION} && git push --tags + git tag --no-sign ${VERSION} && git push --tags flake8: FORCE flake8 $(PYSOURCES) From 72087015b84d949758f96aac2f4cc223d9bfc07f Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Sun, 14 Jul 2024 05:48:27 +0000 Subject: [PATCH 121/165] Fix badgedir.yaml to reproduce #216 --- tests/test-data/badgedir.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test-data/badgedir.yaml b/tests/test-data/badgedir.yaml index 80bd1bd..ea6e551 100644 --- a/tests/test-data/badgedir.yaml +++ b/tests/test-data/badgedir.yaml @@ -32,6 +32,7 @@ tags: [ command_line_tool ] - output: {} + job: null tool: return-unsupported.cwl id: unsupported_wo_job doc: Unsupported test without a job file From 713f6e214f3adb63edbe589aa2d6abf969d0e943 Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Sun, 14 Jul 2024 05:49:17 +0000 Subject: [PATCH 122/165] Fix #216 by considering the case of `job` field with null value --- cwltest/plugin.py | 2 +- cwltest/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cwltest/plugin.py b/cwltest/plugin.py index baa4cae..57a8ab4 100644 --- a/cwltest/plugin.py +++ b/cwltest/plugin.py @@ -67,7 +67,7 @@ def _run_test_hook_or_plain( start_time = time.time() reltool = os.path.relpath(test["tool"], start=config.test_basedir) tooluri = urljoin(config.test_baseuri, reltool) - if "job" in test: + if test.get("job", None): reljob = os.path.relpath(test["job"], start=config.test_basedir) joburi = urljoin(config.test_baseuri, reljob) else: diff --git a/cwltest/utils.py b/cwltest/utils.py index d2fa57e..3a6a15b 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -440,7 +440,7 @@ def run_test_plain( reltool = os.path.relpath(test["tool"], start=config.test_basedir) tooluri = urljoin(config.test_baseuri, reltool) - if "job" in test: + if test.get("job", None): reljob = os.path.relpath(test["job"], start=config.test_basedir) joburi = urljoin(config.test_baseuri, reljob) else: From bc6445651af013be193e0407746db6f171ef6ddc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2024 00:08:16 +0000 Subject: [PATCH 123/165] Bump mypy from 1.10.1 to 1.11.1 Bumps [mypy](https://github.com/python/mypy) from 1.10.1 to 1.11.1. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.10.1...v1.11.1) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 43adedd..2002bdc 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.10.1 +mypy==1.11.1 types-setuptools types-requests types-PyYAML From 8db140eb542bd8cd1ba62539120ff7c4b0da9b8c Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Wed, 31 Jul 2024 15:31:52 +0200 Subject: [PATCH 124/165] pytest 8.3 changed an internal detail --- cwltest/plugin.py | 4 ++-- mypy-requirements.txt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cwltest/plugin.py b/cwltest/plugin.py index 57a8ab4..a27ee92 100644 --- a/cwltest/plugin.py +++ b/cwltest/plugin.py @@ -28,7 +28,7 @@ from cwltest import REQUIRED, UNSUPPORTED_FEATURE, logger, utils if TYPE_CHECKING: - from _pytest._code.code import ExceptionInfo, _TracebackStyle + from _pytest._code.code import ExceptionInfo, TracebackStyle from _pytest.config import Config from _pytest.config import Config as PytestConfig from _pytest.config import PytestPluginManager @@ -207,7 +207,7 @@ def runtest(self) -> None: def repr_failure( self, excinfo: "ExceptionInfo[BaseException]", - style: Optional["_TracebackStyle"] = None, + style: Optional["TracebackStyle"] = None, ) -> str: """ Document failure reason. diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 2002bdc..0976a9f 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,5 @@ mypy==1.11.1 +pytest >= 8.3, < 9 types-setuptools types-requests types-PyYAML From 3282914fc58d635a048a70416fa32b29f45ed17c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 00:43:33 +0000 Subject: [PATCH 125/165] Update black requirement from ~=24.4 to ~=24.8 Updates the requirements on [black](https://github.com/psf/black) to permit the latest version. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/24.4.0...24.8.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index 4280a59..32b201d 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ diff_cover -black ~= 24.4 +black ~= 24.8 pylint pep257 pydocstyle From 291f0d66b83357257cb99aac167de887698efc7f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 00:16:08 +0000 Subject: [PATCH 126/165] Bump mypy from 1.11.1 to 1.11.2 Bumps [mypy](https://github.com/python/mypy) from 1.11.1 to 1.11.2. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.11.1...v1.11.2) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 0976a9f..bf3c7c3 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.11.1 +mypy==1.11.2 pytest >= 8.3, < 9 types-setuptools types-requests From 59c4cc450b6f4ecc94b4d9ba275749280dde9eb1 Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Fri, 6 Sep 2024 14:59:16 +0100 Subject: [PATCH 127/165] Fix B910 errors from flake8-bugbear --- cwltest/main.py | 4 ++-- cwltest/utils.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cwltest/main.py b/cwltest/main.py index 4909c89..a731531 100644 --- a/cwltest/main.py +++ b/cwltest/main.py @@ -4,7 +4,7 @@ import argparse import os import sys -from collections import defaultdict +from collections import Counter, defaultdict from concurrent.futures import ThreadPoolExecutor from typing import Dict, List, Optional, Set, cast @@ -116,7 +116,7 @@ def main() -> int: suite_name, _ = os.path.splitext(os.path.basename(args.test)) report: Optional[junit_xml.TestSuite] = junit_xml.TestSuite(suite_name, []) - ntotal: Dict[str, int] = defaultdict(int) + ntotal: Dict[str, int] = Counter() npassed: Dict[str, List[CWLTestReport]] = defaultdict(list) if args.only_tools: diff --git a/cwltest/utils.py b/cwltest/utils.py index 3a6a15b..b9cd745 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -7,7 +7,7 @@ import sys import tempfile import time -from collections import defaultdict +from collections import Counter, defaultdict from typing import ( Any, Dict, @@ -314,7 +314,7 @@ def parse_results( passed = 0 failures = 0 unsupported = 0 - ntotal: Dict[str, int] = defaultdict(int) + ntotal: Dict[str, int] = Counter() nfailures: Dict[str, List[CWLTestReport]] = defaultdict(list) nunsupported: Dict[str, List[CWLTestReport]] = defaultdict(list) npassed: Dict[str, List[CWLTestReport]] = defaultdict(list) From 90008b837ee4b325efe12a30dce40e926ed69e65 Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Fri, 6 Sep 2024 13:51:38 +0100 Subject: [PATCH 128/165] Add support for Python 3.13 Fix https://github.com/common-workflow-language/cwltest/issues/223 . --- .github/workflows/ci-tests.yml | 4 ++- README.rst | 2 +- pyproject.toml | 3 +- tox.ini | 57 +++++++++++++++++----------------- 4 files changed, 35 insertions(+), 31 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 691a145..152b8fe 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -18,10 +18,11 @@ jobs: runs-on: ubuntu-20.04 # 22.04 doesn't support Python 3.6 strategy: + fail-fast: false matrix: # The README.rst file mentions the versions tested, please update it as well py-ver-major: [3] - py-ver-minor: [8, 9, 10, 11, 12] + py-ver-minor: [8, 9, 10, 11, 12, 13] step: [lint, unit, mypy, bandit] env: @@ -37,6 +38,7 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ env.py-semver }} + allow-prereleases: true cache: pip cache-dependency-path: | requirements.txt diff --git a/README.rst b/README.rst index c4c50dd..d1cc50e 100644 --- a/README.rst +++ b/README.rst @@ -32,7 +32,7 @@ This is a testing tool for checking the output of Tools and Workflows described with the Common Workflow Language. Among other uses, it is used to run the CWL conformance tests. -This is written and tested for Python 3.8, 3.9, 3.10, 3.11, and 3.12. +This is written and tested for Python 3.8, 3.9, 3.10, 3.11, 3.12, and 3.13. .. contents:: Table of Contents :local: diff --git a/pyproject.toml b/pyproject.toml index ddc54be..8daf19f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,9 +22,10 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Typing :: Typed", ] -requires-python = ">=3.8,<3.13" +requires-python = ">=3.8,<3.14" dynamic = ["version", "dependencies"] [project.readme] diff --git a/tox.ini b/tox.ini index f036283..93aadfa 100644 --- a/tox.ini +++ b/tox.ini @@ -1,9 +1,9 @@ [tox] envlist = - py3{8,9,10,11,12}-lint, - py3{8,9,10,11,12}-unit, - py3{8,9,10,11,12}-bandit, - py3{8,9,10,11,12}-mypy, + py3{8,9,10,11,12,13}-lint, + py3{8,9,10,11,12,13}-unit, + py3{8,9,10,11,12,13}-bandit, + py3{8,9,10,11,12,13}-mypy, py312-lintreadme, py312-pydocstyle @@ -22,16 +22,17 @@ python = 3.10: py310 3.11: py311 3.12: py312 + 3.13: py313 [testenv] skipsdist = - py3{8,9,10,11,12}-!{unit,mypy,lintreadme} = True + py3{8,9,10,11,12,13}-!{unit,mypy,lintreadme} = True description = - py3{8,9,10,11,12}-unit: Run the unit tests - py3{8,9,10,11,12}-lint: Lint the Python code - py3{8,9,10,11,12}-bandit: Search for common security issues - py3{8,9,10,11,12}-mypy: Check for type safety + py3{8,9,10,11,12,13}-unit: Run the unit tests + py3{8,9,10,11,12,13}-lint: Lint the Python code + py3{8,9,10,11,12,13}-bandit: Search for common security issues + py3{8,9,10,11,12,13}-mypy: Check for type safety py312-pydocstyle: docstring style checker py312-lintreadme: Lint the README.rst->.md conversion @@ -40,36 +41,36 @@ passenv = GITHUB_* deps = - py3{8,9,10,11,12}-{unit,mypy}: -rrequirements.txt - py3{8,9,10,11,12}-{unit,mypy}: -rtest-requirements.txt - py3{8,9,10,11,12}-lint: flake8-bugbear - py3{8,9,10,11,12}-lint: black~=23.1 - py3{8,9,10,11,12}-bandit: bandit - py3{8,9,10,11,12}-mypy: -rmypy-requirements.txt + py3{8,9,10,11,12,13}-{unit,mypy}: -rrequirements.txt + py3{8,9,10,11,12,13}-{unit,mypy}: -rtest-requirements.txt + py3{8,9,10,11,12,13}-lint: flake8-bugbear + py3{8,9,10,11,12,13}-lint: black~=23.1 + py3{8,9,10,11,12,13}-bandit: bandit + py3{8,9,10,11,12,13}-mypy: -rmypy-requirements.txt set_env = - py3{8,3,10,11,12}-unit: LC_ALL = C.UTF-8 + py3{8,3,10,11,12,13}-unit: LC_ALL = C.UTF-8 COV_CORE_SOURCE=cwltest COV_CORE_CONFIG={toxinidir}/.coveragerc COV_CORE_DATAFILE={toxinidir}/.coverage.eager commands = - py3{8,9,10,11,12}-unit: python -m pip install -U pip setuptools wheel - py3{8,9,10,11,12}-unit: python -m pytest --cov --cov-config={toxinidir}/.coveragerc --cov-append {posargs} - py3{8,9,10,11,12}-unit: coverage xml - py3{8,9,10,11,12}-bandit: bandit --recursive cwltest - py3{8,9,10,11,12}-lint: make flake8 - py3{8,9,10,11,12}-lint: make format-check - py3{8,9,10,11,12}-mypy: make mypy + py3{8,9,10,11,12,13}-unit: python -m pip install -U pip setuptools wheel + py3{8,9,10,11,12,13}-unit: python -m pytest --cov --cov-config={toxinidir}/.coveragerc --cov-append {posargs} + py3{8,9,10,11,12,13}-unit: coverage xml + py3{8,9,10,11,12,13}-bandit: bandit --recursive cwltest + py3{8,9,10,11,12,13}-lint: make flake8 + py3{8,9,10,11,12,13}-lint: make format-check + py3{8,9,10,11,12,13}-mypy: make mypy allowlist_externals = - py3{8,9,10,11,12}-lint: flake8 - py3{8,9,10,11,12}-lint: black - py3{8,9,10,11,12}-{mypy,shellcheck,lint,unit}: make + py3{8,9,10,11,12,13}-lint: flake8 + py3{8,9,10,11,12,13}-lint: black + py3{8,9,10,11,12,13}-{mypy,shellcheck,lint,unit}: make skip_install = - py3{8,9,10,11,12}-lint: true - py3{8,9,10,11,12}-bandit: true + py3{8,9,10,11,12,13}-lint: true + py3{8,9,10,11,12,13}-bandit: true [testenv:py312-pydocstyle] From f7ce9445a91cc405b8bec21cca10550a5e08ef74 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 00:03:39 +0000 Subject: [PATCH 129/165] Update black requirement from ~=24.8 to ~=24.10 Updates the requirements on [black](https://github.com/psf/black) to permit the latest version. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/24.8.0...24.10.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index 32b201d..0316d33 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ diff_cover -black ~= 24.8 +black ~= 24.10 pylint pep257 pydocstyle From 4889565a4f0fdd16a36457a336558f1436529f88 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 03:31:00 +0000 Subject: [PATCH 130/165] Bump sphinx-rtd-theme from 2.0.0 to 3.0.0 Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 2.0.0 to 3.0.0. - [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst) - [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/2.0.0...3.0.0) --- updated-dependencies: - dependency-name: sphinx-rtd-theme dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 1cdb96e..fdfa727 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ sphinx >= 2.2 -sphinx-rtd-theme==2.0.0 +sphinx-rtd-theme==3.0.0 sphinx-autoapi sphinx-autodoc-typehints typed_ast;python_version<'3.8' From 9e2c3952d5c8f678c22583c96e82021c87fa0719 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Oct 2024 00:43:58 +0000 Subject: [PATCH 131/165] Bump sphinx-rtd-theme from 3.0.0 to 3.0.1 Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 3.0.0 to 3.0.1. - [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst) - [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/3.0.0...3.0.1) --- updated-dependencies: - dependency-name: sphinx-rtd-theme dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index fdfa727..545b2ae 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ sphinx >= 2.2 -sphinx-rtd-theme==3.0.0 +sphinx-rtd-theme==3.0.1 sphinx-autoapi sphinx-autodoc-typehints typed_ast;python_version<'3.8' From 9afd074c36e4f99d0e461f8539ecc2daef8f3a78 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 00:42:02 +0000 Subject: [PATCH 132/165] Bump mypy from 1.11.2 to 1.12.0 Bumps [mypy](https://github.com/python/mypy) from 1.11.2 to 1.12.0. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.11.2...v1.12.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index bf3c7c3..94e56a2 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.11.2 +mypy==1.12.0 pytest >= 8.3, < 9 types-setuptools types-requests From 70f115fe5eafdb149e61ed74ecdf3724ca28d81b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 00:53:36 +0000 Subject: [PATCH 133/165] Bump mypy from 1.12.0 to 1.12.1 Bumps [mypy](https://github.com/python/mypy) from 1.12.0 to 1.12.1. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.12.0...v1.12.1) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 94e56a2..b75562f 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.12.0 +mypy==1.12.1 pytest >= 8.3, < 9 types-setuptools types-requests From 3ece638a7d6c280c202d6cbc71f6ccfc1f1bd1e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 00:57:51 +0000 Subject: [PATCH 134/165] Bump mypy from 1.12.1 to 1.13.0 Bumps [mypy](https://github.com/python/mypy) from 1.12.1 to 1.13.0. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.12.1...v1.13.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index b75562f..1f01ab5 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.12.1 +mypy==1.13.0 pytest >= 8.3, < 9 types-setuptools types-requests From 18bafe2b3f9c58a1915e22f5a02bcba5dc4ed2dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 00:12:45 +0000 Subject: [PATCH 135/165] Bump sphinx-rtd-theme from 3.0.1 to 3.0.2 Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 3.0.1 to 3.0.2. - [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst) - [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/3.0.1...3.0.2) --- updated-dependencies: - dependency-name: sphinx-rtd-theme dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 545b2ae..8c1e1f4 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ sphinx >= 2.2 -sphinx-rtd-theme==3.0.1 +sphinx-rtd-theme==3.0.2 sphinx-autoapi sphinx-autodoc-typehints typed_ast;python_version<'3.8' From feeb0da1475d5cdce9f2dba167d35475f220e5c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 00:40:40 +0000 Subject: [PATCH 136/165] Bump codecov/codecov-action from 3 to 5 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 5. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v3...v5) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 152b8fe..1907d13 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -62,7 +62,7 @@ jobs: - name: Upload coverage to Codecov if: ${{ matrix.step == 'unit' }} - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v5 with: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} From fc92b4863ac4720d5d0bf2e4036591f200fa2ff0 Mon Sep 17 00:00:00 2001 From: Peter Amstutz Date: Fri, 22 Nov 2024 08:33:19 -0500 Subject: [PATCH 137/165] support plugins for alternative FsAccess (#233) Arvados-DCO-1.1-Signed-off-by: Peter Amstutz --- README.rst | 54 ++++++++++++++++++++++++++++++++++++++++++ cwltest/compare.py | 30 +++++++++++++---------- cwltest/main.py | 9 ++++++- cwltest/stdfsaccess.py | 48 +++++++++++++++++++++++++++++++++++++ cwltest/utils.py | 38 +++++++++++++++++++++++++++++ 5 files changed, 166 insertions(+), 13 deletions(-) create mode 100644 cwltest/stdfsaccess.py diff --git a/README.rst b/README.rst index d1cc50e..f5f646a 100644 --- a/README.rst +++ b/README.rst @@ -91,3 +91,57 @@ Once you upload JSON file to a server, you make a badge by using a link like htt Here is an example of markdown to add a badge:: ![test result](https://flat.badgen.net/https/path/to/generated/json?icon=commonwl) + +************************* +Custom file access module +************************* + +If your CWL implementation does not write output files to a local file +system location but instead to some other remote storage system, you +can provide an alternate implementation of the *StdFsAccess* object +that is able to access your storage system. + +Step 1: + +Implement your own class with the same public interface of the +*StdFsAccess* object in *cwltest/stdfsaccess.py* (as of this writing, +the methods are *open*, *size*, *isfile* and *isdir*). These methods +should expect to be called with URIs from the *location* field of the +outputs of test cases. + +Define a function that, when called, returns a new instance of your object. + +Step 2: + +Create a Python package containing your class (or add it to an +existing one). + +In the package metadata, add an entry point that declares the module +(in this example, *my_cwl_runner.fsaccess*) containing the function +(in this example, *get_fsaccess*) that *cwltest* will invoke to get an +object implementing the *StdFsAccess* interface. + +In *setup.py* this looks like: + +.. code:: python + + setup( + ... + entry_points={"cwltest.fsaccess": ["fsaccess=my_cwl_runner.fsaccess:get_fsaccess"]}}, + ... + ) + +In *pyproject.toml* it looks like: + +.. code:: + + [project.entry-points.'cwltest.fsaccess'] + fsaccess = 'my_cwl_runner.fsaccess:get_fsaccess' + + +Step 3: + +Install your package in the same Python environemnt as the +installation of *cwltest*. When invoked, *cwltest* will query Python +package metadata for a package with the *cwltest.fsaccess* entry point +and call it to get back a custom filesystem access object. diff --git a/cwltest/compare.py b/cwltest/compare.py index 18452ed..0e3008b 100644 --- a/cwltest/compare.py +++ b/cwltest/compare.py @@ -2,9 +2,10 @@ import hashlib import json -import os.path -import urllib.parse from typing import Any, Callable, Dict, Optional, Set +import cwltest.stdfsaccess + +fs_access = cwltest.stdfsaccess.StdFsAccess("") class CompareFail(Exception): @@ -130,13 +131,14 @@ def _compare_location( actual_comp = "path" else: actual_comp = "location" - path = urllib.parse.urlparse(actual[actual_comp]).path + if actual.get("class") == "Directory": actual[actual_comp] = actual[actual_comp].rstrip("/") - exist_fun: Callable[[str], bool] = os.path.isdir + exist_fun: Callable[[str], bool] = fs_access.isdir else: - exist_fun = os.path.isfile - if not exist_fun(path) and not skip_details: + exist_fun = fs_access.isfile + + if not exist_fun(actual[actual_comp]) and not skip_details: raise CompareFail.format( expected, actual, @@ -160,15 +162,17 @@ def _compare_location( def _compare_checksum(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: if "path" in actual: - path = urllib.parse.urlparse(actual["path"]).path + path = actual["path"] else: - path = urllib.parse.urlparse(actual["location"]).path + path = actual["location"] checksum = hashlib.sha1() # nosec - with open(path, "rb") as f: + + with fs_access.open(path, "rb") as f: contents = f.read(1024 * 1024) while contents != b"": checksum.update(contents) contents = f.read(1024 * 1024) + actual_checksum_on_disk = f"sha1${checksum.hexdigest()}" if "checksum" in actual: actual_checksum_declared = actual["checksum"] @@ -193,10 +197,12 @@ def _compare_checksum(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: def _compare_size(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: if "path" in actual: - path = urllib.parse.urlparse(actual["path"]).path + path = actual["path"] else: - path = urllib.parse.urlparse(actual["location"]).path - actual_size_on_disk = os.path.getsize(path) + path = actual["location"] + + actual_size_on_disk = fs_access.size(path) + if "size" in actual: actual_size_declared = actual["size"] if actual_size_on_disk != actual_size_declared: diff --git a/cwltest/main.py b/cwltest/main.py index a731531..d8a7218 100644 --- a/cwltest/main.py +++ b/cwltest/main.py @@ -13,7 +13,12 @@ import schema_salad.ref_resolver import schema_salad.schema from cwltest.argparser import arg_parser -from cwltest.utils import CWLTestConfig, CWLTestReport, TestResult +from cwltest.utils import ( + CWLTestConfig, + CWLTestReport, + TestResult, + load_optional_fsaccess_plugin, +) from schema_salad.exceptions import ValidationException from cwltest import logger, utils @@ -116,6 +121,8 @@ def main() -> int: suite_name, _ = os.path.splitext(os.path.basename(args.test)) report: Optional[junit_xml.TestSuite] = junit_xml.TestSuite(suite_name, []) + load_optional_fsaccess_plugin() + ntotal: Dict[str, int] = Counter() npassed: Dict[str, List[CWLTestReport]] = defaultdict(list) diff --git a/cwltest/stdfsaccess.py b/cwltest/stdfsaccess.py new file mode 100644 index 0000000..b59375e --- /dev/null +++ b/cwltest/stdfsaccess.py @@ -0,0 +1,48 @@ +"""Abstracted IO access.""" + +import os +import urllib +from typing import IO, Any + +from schema_salad.ref_resolver import uri_file_path + + +def abspath(src: str, basedir: str) -> str: + """Determine local filesystem absolute path given a basedir, handling both plain paths and URIs.""" + if src.startswith("file://"): + abpath = uri_file_path(src) + elif urllib.parse.urlsplit(src).scheme in ["http", "https"]: + return src + else: + if basedir.startswith("file://"): + abpath = src if os.path.isabs(src) else basedir + "/" + src + else: + abpath = src if os.path.isabs(src) else os.path.join(basedir, src) + return abpath + + +class StdFsAccess: + """Local filesystem implementation.""" + + def __init__(self, basedir: str) -> None: + """Perform operations with respect to a base directory.""" + self.basedir = basedir + + def _abs(self, p: str) -> str: + return abspath(p, self.basedir) + + def open(self, fn: str, mode: str) -> IO[Any]: + """Open a file from a file: URI.""" + return open(self._abs(fn), mode) + + def size(self, fn: str) -> int: + """Get the size of the file resource pointed to by a URI.""" + return os.stat(self._abs(fn)).st_size + + def isfile(self, fn: str) -> bool: + """Determine if a resource pointed to by a URI represents a file.""" + return os.path.isfile(self._abs(fn)) + + def isdir(self, fn: str) -> bool: + """Determine if a resource pointed to by a URI represents a directory.""" + return os.path.isdir(self._abs(fn)) diff --git a/cwltest/utils.py b/cwltest/utils.py index b9cd745..a638042 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -27,6 +27,8 @@ import schema_salad.avro import schema_salad.ref_resolver import schema_salad.schema +import cwltest.compare +import cwltest.stdfsaccess from cwltest.compare import CompareFail, compare from rdflib import Graph from ruamel.yaml.scalarstring import ScalarString @@ -37,6 +39,10 @@ else: from importlib_resources import as_file, files +# available since Python 3.8 (minimum version supports as of this +# writing) so we don't need to fuss with backports +from importlib.metadata import entry_points, EntryPoint + from cwltest import REQUIRED, UNSUPPORTED_FEATURE, logger, templock __all__ = ["files", "as_file"] @@ -659,3 +665,35 @@ def absuri(path: str) -> str: if "://" in path: return path return "file://" + os.path.abspath(path) + + +def load_optional_fsaccess_plugin() -> None: + """ + Load optional fsaccess plugin. + + Looks for a package with cwltest.fsaccess entry point and if so, + use that to get a filesystem access object that will be used for + checking test output. + """ + fsaccess_eps: List[EntryPoint] + + try: + # The interface to importlib.metadata.entry_points() changed + # several times between Python 3.8 and 3.13; the code below + # actually works fine on all of them but there's no single + # mypy annotation that works across of them. Explicitly cast + # it to a consistent type to make mypy shut up. + fsaccess_eps = cast(List[EntryPoint], entry_points()["cwltest.fsaccess"]) # type: ignore [redundant-cast, unused-ignore] + except KeyError: + return + + if len(fsaccess_eps) == 0: + return + + if len(fsaccess_eps) > 1: + logger.warn( + "More than one cwltest.fsaccess entry point found, selected %s", + fsaccess_eps[0], + ) + + cwltest.compare.fs_access = fsaccess_eps[0].load()() From b54c3ba42df1f9eeca317d857f7971d4555823a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 22 Dec 2024 16:42:16 -0800 Subject: [PATCH 138/165] Bump mypy from 1.13.0 to 1.14.0 (#234) Bumps [mypy](https://github.com/python/mypy) from 1.13.0 to 1.14.0. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.13.0...v1.14.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 1f01ab5..ad380f0 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.13.0 +mypy==1.14.0 pytest >= 8.3, < 9 types-setuptools types-requests From 8b5cdbc9d96b44f0eebafc4efdda0355ff3eed12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jan 2025 22:51:16 +0100 Subject: [PATCH 139/165] Bump mypy from 1.14.0 to 1.14.1 (#235) Bumps [mypy](https://github.com/python/mypy) from 1.14.0 to 1.14.1. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.14.0...v1.14.1) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index ad380f0..5f2bb8c 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.14.0 +mypy==1.14.1 pytest >= 8.3, < 9 types-setuptools types-requests From 68781bc883903a79d8ab1d15502eae6c41fdfbc2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Jan 2025 14:53:38 +0100 Subject: [PATCH 140/165] Update black requirement from ~=24.10 to ~=25.1 (#236) Updates the requirements on [black](https://github.com/psf/black) to permit the latest version. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/24.10.0...25.1.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index 0316d33..c5c27be 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ diff_cover -black ~= 24.10 +black ~= 25.1 pylint pep257 pydocstyle From 5df6c58a3139f2cec35db01493134806820d4cde Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Feb 2025 00:13:12 +0000 Subject: [PATCH 141/165] Bump mypy from 1.14.1 to 1.15.0 Bumps [mypy](https://github.com/python/mypy) from 1.14.1 to 1.15.0. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.14.1...v1.15.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 5f2bb8c..1327dd1 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.14.1 +mypy==1.15.0 pytest >= 8.3, < 9 types-setuptools types-requests From 55025bc3bb7930c00a29bad150fb28f8f59f37c6 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Thu, 6 Feb 2025 12:56:20 +0100 Subject: [PATCH 142/165] drop mypy from the Python 3.8 configuration --- .github/workflows/ci-tests.yml | 3 +++ tox.ini | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 1907d13..88dc10e 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -24,6 +24,9 @@ jobs: py-ver-major: [3] py-ver-minor: [8, 9, 10, 11, 12, 13] step: [lint, unit, mypy, bandit] + exclude: + - step: mypy + py-ver-minor: 8 env: py-semver: ${{ format('{0}.{1}', matrix.py-ver-major, matrix.py-ver-minor) }} diff --git a/tox.ini b/tox.ini index 93aadfa..0d54cfb 100644 --- a/tox.ini +++ b/tox.ini @@ -3,7 +3,7 @@ envlist = py3{8,9,10,11,12,13}-lint, py3{8,9,10,11,12,13}-unit, py3{8,9,10,11,12,13}-bandit, - py3{8,9,10,11,12,13}-mypy, + py3{9,10,11,12,13}-mypy, py312-lintreadme, py312-pydocstyle @@ -32,7 +32,7 @@ description = py3{8,9,10,11,12,13}-unit: Run the unit tests py3{8,9,10,11,12,13}-lint: Lint the Python code py3{8,9,10,11,12,13}-bandit: Search for common security issues - py3{8,9,10,11,12,13}-mypy: Check for type safety + py3{9,10,11,12,13}-mypy: Check for type safety py312-pydocstyle: docstring style checker py312-lintreadme: Lint the README.rst->.md conversion @@ -46,7 +46,7 @@ deps = py3{8,9,10,11,12,13}-lint: flake8-bugbear py3{8,9,10,11,12,13}-lint: black~=23.1 py3{8,9,10,11,12,13}-bandit: bandit - py3{8,9,10,11,12,13}-mypy: -rmypy-requirements.txt + py3{9,10,11,12,13}-mypy: -rmypy-requirements.txt set_env = py3{8,3,10,11,12,13}-unit: LC_ALL = C.UTF-8 @@ -61,7 +61,7 @@ commands = py3{8,9,10,11,12,13}-bandit: bandit --recursive cwltest py3{8,9,10,11,12,13}-lint: make flake8 py3{8,9,10,11,12,13}-lint: make format-check - py3{8,9,10,11,12,13}-mypy: make mypy + py3{9,10,11,12,13}-mypy: make mypy allowlist_externals = py3{8,9,10,11,12,13}-lint: flake8 From e8a70ca5aa07141939970bd1dea9b05a6b880bc6 Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Wed, 12 Feb 2025 13:58:49 +0000 Subject: [PATCH 143/165] Replace ubuntu-20.04 runner (#238) https://github.blog/changelog/2025-01-15-github-actions-ubuntu-20-runner-image-brownout-dates-and-other-breaking-changes/ --- .github/workflows/ci-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 88dc10e..dcc41e0 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -15,7 +15,7 @@ jobs: tox: name: CI tests via Tox - runs-on: ubuntu-20.04 # 22.04 doesn't support Python 3.6 + runs-on: ubuntu-latest strategy: fail-fast: false From e4b0d02baf9e43006f6a16ed8ed7b100e42a417e Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 14 Mar 2025 14:19:48 +0100 Subject: [PATCH 144/165] Badges: compute a fake 'all' tag, containing all tests --- cwltest/argparser.py | 3 ++- cwltest/plugin.py | 3 ++- cwltest/utils.py | 5 ++++- tests/test_badgedir.py | 9 +++++++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/cwltest/argparser.py b/cwltest/argparser.py index 1d2458c..b5698cf 100644 --- a/cwltest/argparser.py +++ b/cwltest/argparser.py @@ -107,7 +107,8 @@ def arg_parser() -> argparse.ArgumentParser: parser.add_argument( "--badgedir", type=str, - help="Create JSON badges and store them in this directory.", + help="Create JSON badges, one for each tag (plus a computed 'all' tag) " + " and store them in this directory.", ) try: diff --git a/cwltest/plugin.py b/cwltest/plugin.py index a27ee92..4d89412 100644 --- a/cwltest/plugin.py +++ b/cwltest/plugin.py @@ -325,7 +325,8 @@ def collect(self) -> Iterator[CWLItem]: "--cwl-badgedir", { "type": str, - "help": "Create badge JSON files and store them in this directory.", + "help": "Create badge JSON files, one for each tag (plus a computed " + "'all' tag), and store them in this directory.", }, ), ( diff --git a/cwltest/utils.py b/cwltest/utils.py index a638042..9c8ed25 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -313,6 +313,9 @@ def parse_results( """ Parse the results and return statistics and an optional report. + An additional tag named "all" will be computed, containing all the test + results. + Returns the total number of tests, dictionary of test counts (total, passed, failed, unsupported) by tag, and a jUnit XML report. """ @@ -334,7 +337,7 @@ def parse_results( else "cwltest:#{i + 1}" ) total += 1 - tags = tests[i].get("tags", []) + tags = tests[i].get("tags", []) + ["all"] for t in tags: ntotal[t] += 1 diff --git a/tests/test_badgedir.py b/tests/test_badgedir.py index cf2f3ac..fa421df 100644 --- a/tests/test_badgedir.py +++ b/tests/test_badgedir.py @@ -53,6 +53,15 @@ def test_badgedir(tmp_path: Path) -> None: assert obj.get("color", "") == "yellow" assert (badgedir / "command_line_tool.md").exists() + all_tests = badgedir / "all.json" + assert all_tests.exists() + with open(all_tests) as file: + obj = json.load(file) + assert obj.get("subject", "") == "all" + assert obj.get("status", "") == "0%" + assert obj.get("color", "") == "yellow" + assert (badgedir / "all.md").exists() + def test_badgedir_report_with_baseuri(tmp_path: Path) -> None: badgedir = tmp_path / "badgedir" From a8113b19dbee334a856680305516751c618c9274 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 14 Mar 2025 14:20:09 +0100 Subject: [PATCH 145/165] Drop support for Python 3.8 miscellaneous formatting & pyupgrade --- .github/workflows/ci-tests.yml | 5 +- Makefile | 2 +- README.rst | 2 +- cwltest/compare.py | 19 ++--- cwltest/hooks.py | 4 +- cwltest/main.py | 20 +++--- cwltest/plugin.py | 45 +++++------- cwltest/utils.py | 126 ++++++++++++++------------------- docs/requirements.txt | 1 - pyproject.toml | 3 +- requirements.txt | 1 - tests/test_badgedir.py | 2 +- tests/test_compare.py | 9 +-- tests/util.py | 9 ++- tox.ini | 49 +++++++------ 15 files changed, 131 insertions(+), 166 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index dcc41e0..7875d79 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -22,11 +22,8 @@ jobs: matrix: # The README.rst file mentions the versions tested, please update it as well py-ver-major: [3] - py-ver-minor: [8, 9, 10, 11, 12, 13] + py-ver-minor: [9, 10, 11, 12, 13] step: [lint, unit, mypy, bandit] - exclude: - - step: mypy - py-ver-minor: 8 env: py-semver: ${{ format('{0}.{1}', matrix.py-ver-major, matrix.py-ver-minor) }} diff --git a/Makefile b/Makefile index 097ccc6..9abf584 100644 --- a/Makefile +++ b/Makefile @@ -168,7 +168,7 @@ mypy: $(PYSOURCES) MYPYPATH=$$MYPYPATH:mypy-stubs mypy $^ pyupgrade: $(filter-out schema_salad/metaschema.py,$(PYSOURCES)) - pyupgrade --exit-zero-even-if-changed --py38-plus $^ + pyupgrade --exit-zero-even-if-changed --py39-plus $^ auto-walrus $^ release-test: FORCE diff --git a/README.rst b/README.rst index f5f646a..7c17c99 100644 --- a/README.rst +++ b/README.rst @@ -32,7 +32,7 @@ This is a testing tool for checking the output of Tools and Workflows described with the Common Workflow Language. Among other uses, it is used to run the CWL conformance tests. -This is written and tested for Python 3.8, 3.9, 3.10, 3.11, 3.12, and 3.13. +This is written and tested for Python 3.9, 3.10, 3.11, 3.12, and 3.13. .. contents:: Table of Contents :local: diff --git a/cwltest/compare.py b/cwltest/compare.py index 0e3008b..9af3561 100644 --- a/cwltest/compare.py +++ b/cwltest/compare.py @@ -2,7 +2,8 @@ import hashlib import json -from typing import Any, Callable, Dict, Optional, Set +from typing import Any, Callable, Optional + import cwltest.stdfsaccess fs_access = cwltest.stdfsaccess.StdFsAccess("") @@ -26,7 +27,7 @@ def format( def _check_keys( - keys: Set[str], expected: Dict[str, Any], actual: Dict[str, Any], skip_details: bool + keys: set[str], expected: dict[str, Any], actual: dict[str, Any], skip_details: bool ) -> None: for k in keys: try: @@ -37,7 +38,7 @@ def _check_keys( ) from e -def _compare_contents(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: +def _compare_contents(expected: dict[str, Any], actual: dict[str, Any]) -> None: with open(actual["path"]) as f: actual_contents = f.read() if (expected_contents := expected["contents"]) != actual_contents: @@ -52,7 +53,7 @@ def _compare_contents(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: def _compare_dict( - expected: Dict[str, Any], actual: Dict[str, Any], skip_details: bool + expected: dict[str, Any], actual: dict[str, Any], skip_details: bool ) -> None: for c in expected: try: @@ -68,7 +69,7 @@ def _compare_dict( def _compare_directory( - expected: Dict[str, Any], actual: Dict[str, Any], skip_details: bool + expected: dict[str, Any], actual: dict[str, Any], skip_details: bool ) -> None: if actual.get("class") != "Directory": raise CompareFail.format( @@ -97,7 +98,7 @@ def _compare_directory( def _compare_file( - expected: Dict[str, Any], actual: Dict[str, Any], skip_details: bool + expected: dict[str, Any], actual: dict[str, Any], skip_details: bool ) -> None: _compare_location(expected, actual, skip_details) if "contents" in expected: @@ -117,7 +118,7 @@ def _compare_file( def _compare_location( - expected: Dict[str, Any], actual: Dict[str, Any], skip_details: bool + expected: dict[str, Any], actual: dict[str, Any], skip_details: bool ) -> None: if "path" in expected: expected_comp = "path" @@ -160,7 +161,7 @@ def _compare_location( ) -def _compare_checksum(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: +def _compare_checksum(expected: dict[str, Any], actual: dict[str, Any]) -> None: if "path" in actual: path = actual["path"] else: @@ -195,7 +196,7 @@ def _compare_checksum(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: ) -def _compare_size(expected: Dict[str, Any], actual: Dict[str, Any]) -> None: +def _compare_size(expected: dict[str, Any], actual: dict[str, Any]) -> None: if "path" in actual: path = actual["path"] else: diff --git a/cwltest/hooks.py b/cwltest/hooks.py index 9b3faae..9b792e8 100644 --- a/cwltest/hooks.py +++ b/cwltest/hooks.py @@ -1,13 +1,13 @@ """Hooks for pytest-cwl users.""" -from typing import Any, Dict, Optional, Tuple +from typing import Any, Optional from cwltest import utils def pytest_cwl_execute_test( # type: ignore[empty-body] config: utils.CWLTestConfig, processfile: str, jobfile: Optional[str] -) -> Tuple[int, Optional[Dict[str, Any]]]: +) -> tuple[int, Optional[dict[str, Any]]]: """ Execute CWL test using a Python function instead of a command line runner. diff --git a/cwltest/main.py b/cwltest/main.py index d8a7218..92fe672 100644 --- a/cwltest/main.py +++ b/cwltest/main.py @@ -6,12 +6,15 @@ import sys from collections import Counter, defaultdict from concurrent.futures import ThreadPoolExecutor -from typing import Dict, List, Optional, Set, cast +from typing import Optional, cast import junit_xml import schema_salad.avro import schema_salad.ref_resolver import schema_salad.schema +from schema_salad.exceptions import ValidationException + +from cwltest import logger, utils from cwltest.argparser import arg_parser from cwltest.utils import ( CWLTestConfig, @@ -19,9 +22,6 @@ TestResult, load_optional_fsaccess_plugin, ) -from schema_salad.exceptions import ValidationException - -from cwltest import logger, utils if sys.stderr.isatty(): PREFIX = "\r" @@ -33,7 +33,7 @@ def _run_test( args: argparse.Namespace, - test: Dict[str, str], + test: dict[str, str], test_number: int, total_tests: int, ) -> TestResult: @@ -78,8 +78,8 @@ def _run_test( return utils.run_test_plain(config, test, test_number) -def _expand_number_range(nr: str) -> List[int]: - result: List[int] = [] +def _expand_number_range(nr: str) -> list[int]: + result: list[int] = [] for s in nr.split(","): sp = s.split("-") if len(sp) == 2: @@ -123,8 +123,8 @@ def main() -> int: load_optional_fsaccess_plugin() - ntotal: Dict[str, int] = Counter() - npassed: Dict[str, List[CWLTestReport]] = defaultdict(list) + ntotal: dict[str, int] = Counter() + npassed: dict[str, list[CWLTestReport]] = defaultdict(list) if args.only_tools: alltests = tests @@ -161,7 +161,7 @@ def main() -> int: logger.warning("The `id` field is missing.") if args.show_tags: - alltags: Set[str] = set() + alltags: set[str] = set() for t in tests: ts = t.get("tags", []) alltags |= set(ts) diff --git a/cwltest/plugin.py b/cwltest/plugin.py index 4d89412..c780504 100644 --- a/cwltest/plugin.py +++ b/cwltest/plugin.py @@ -5,27 +5,16 @@ import os import time import traceback +from collections.abc import Iterator from io import StringIO from pathlib import Path -from typing import ( - TYPE_CHECKING, - Any, - Dict, - Iterator, - List, - Optional, - Protocol, - Set, - Tuple, - Union, - cast, -) +from typing import TYPE_CHECKING, Any, Optional, Protocol, Union, cast from urllib.parse import urljoin import pytest -from cwltest.compare import CompareFail, compare from cwltest import REQUIRED, UNSUPPORTED_FEATURE, logger, utils +from cwltest.compare import CompareFail, compare if TYPE_CHECKING: from _pytest._code.code import ExceptionInfo, TracebackStyle @@ -42,12 +31,12 @@ class TestRunner(Protocol): def __call__( self, config: utils.CWLTestConfig, processfile: str, jobfile: Optional[str] - ) -> List[Optional[Dict[str, Any]]]: + ) -> list[Optional[dict[str, Any]]]: """Type signature for pytest_cwl_execute_test hook results.""" ... -def _get_comma_separated_option(config: "Config", name: str) -> List[str]: +def _get_comma_separated_option(config: "Config", name: str) -> list[str]: options = config.getoption(name) if options is None: return [] @@ -58,7 +47,7 @@ def _get_comma_separated_option(config: "Config", name: str) -> List[str]: def _run_test_hook_or_plain( - test: Dict[str, str], + test: dict[str, str], config: utils.CWLTestConfig, hook: "HookCaller", ) -> utils.TestResult: @@ -76,7 +65,7 @@ def _run_test_hook_or_plain( hook_out = hook(config=config, processfile=processfile, jobfile=jobfile) if not hook_out: return utils.run_test_plain(config, test) - returncode, out = cast(Tuple[int, Optional[Dict[str, Any]]], hook_out[0]) + returncode, out = cast(tuple[int, Optional[dict[str, Any]]], hook_out[0]) duration = time.time() - start_time outstr = json.dumps(out) if out is not None else "{}" if returncode == UNSUPPORTED_FEATURE: @@ -164,7 +153,7 @@ def __init__( self, name: str, parent: Optional["Node"], - spec: Dict[str, Any], + spec: dict[str, Any], ) -> None: """Initialize this CWLItem.""" super().__init__(name, parent) @@ -198,7 +187,7 @@ def runtest(self) -> None: hook, ) cwl_results = self.config.cwl_results # type: ignore[attr-defined] - cast(List[Tuple[Dict[str, Any], utils.TestResult]], cwl_results).append( + cast(list[tuple[dict[str, Any], utils.TestResult]], cwl_results).append( (self.spec, result) ) if result.return_code != 0: @@ -238,7 +227,7 @@ def repr_failure( ) ) - def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str]: + def reportinfo(self) -> tuple[Union["os.PathLike[str]", str], Optional[int], str]: """Status report.""" return self.path, 0, "cwl test: %s" % self.name @@ -258,10 +247,10 @@ def _add_global_properties(self) -> None: def collect(self) -> Iterator[CWLItem]: """Load the cwltest file and yield parsed entries.""" - include: Set[str] = set(_get_comma_separated_option(self.config, "cwl_include")) - exclude: Set[str] = set(_get_comma_separated_option(self.config, "cwl_exclude")) - tags: Set[str] = set(_get_comma_separated_option(self.config, "cwl_tags")) - exclude_tags: Set[str] = set( + include: set[str] = set(_get_comma_separated_option(self.config, "cwl_include")) + exclude: set[str] = set(_get_comma_separated_option(self.config, "cwl_exclude")) + tags: set[str] = set(_get_comma_separated_option(self.config, "cwl_tags")) + exclude_tags: set[str] = set( _get_comma_separated_option(self.config, "cwl_exclude_tags") ) tests, _ = utils.load_and_validate_tests(str(self.path)) @@ -302,7 +291,7 @@ def collect(self) -> Iterator[CWLItem]: yield item -__OPTIONS: List[Tuple[str, Dict[str, Any]]] = [ +__OPTIONS: list[tuple[str, dict[str, Any]]] = [ ( "--cwl-runner", { @@ -400,14 +389,14 @@ def pytest_collect_file( def pytest_configure(config: "PytestConfig") -> None: """Store the raw tests and the test results.""" - cwl_results: List[Tuple[Dict[str, Any], utils.TestResult]] = [] + cwl_results: list[tuple[dict[str, Any], utils.TestResult]] = [] config.cwl_results = cwl_results # type: ignore[attr-defined] def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None: """Generate badges.""" cwl_results = cast( - List[Tuple[Dict[str, Any], utils.TestResult]], + list[tuple[dict[str, Any], utils.TestResult]], getattr(session.config, "cwl_results", None), ) if not cwl_results: diff --git a/cwltest/utils.py b/cwltest/utils.py index 9c8ed25..33aee52 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -8,18 +8,10 @@ import tempfile import time from collections import Counter, defaultdict -from typing import ( - Any, - Dict, - Iterable, - List, - MutableMapping, - MutableSequence, - Optional, - Tuple, - Union, - cast, -) +from collections.abc import Iterable, MutableMapping, MutableSequence +from importlib.metadata import EntryPoint, entry_points +from importlib.resources import files +from typing import Any, Optional, Union, cast from urllib.parse import urljoin import junit_xml @@ -27,25 +19,14 @@ import schema_salad.avro import schema_salad.ref_resolver import schema_salad.schema -import cwltest.compare -import cwltest.stdfsaccess -from cwltest.compare import CompareFail, compare from rdflib import Graph from ruamel.yaml.scalarstring import ScalarString from schema_salad.exceptions import ValidationException -if sys.version_info >= (3, 9): - from importlib.resources import as_file, files -else: - from importlib_resources import as_file, files - -# available since Python 3.8 (minimum version supports as of this -# writing) so we don't need to fuss with backports -from importlib.metadata import entry_points, EntryPoint - +import cwltest.compare +import cwltest.stdfsaccess from cwltest import REQUIRED, UNSUPPORTED_FEATURE, logger, templock - -__all__ = ["files", "as_file"] +from cwltest.compare import CompareFail, compare class CWLTestConfig: @@ -61,8 +42,8 @@ def __init__( outdir: Optional[str] = None, classname: Optional[str] = None, tool: Optional[str] = None, - args: Optional[List[str]] = None, - testargs: Optional[List[str]] = None, + args: Optional[list[str]] = None, + testargs: Optional[list[str]] = None, timeout: Optional[int] = None, verbose: Optional[bool] = None, runner_quiet: Optional[bool] = None, @@ -77,8 +58,8 @@ def __init__( self.test_baseuri, os.path.basename(entry) + f"#L{entry_line}" ) self.tool: str = tool or "cwl-runner" - self.args: List[str] = args or [] - self.testargs: List[str] = testargs or [] + self.args: list[str] = args or [] + self.testargs: list[str] = testargs or [] self.timeout: Optional[int] = timeout self.verbose: bool = verbose or False self.runner_quiet: bool = runner_quiet or True @@ -88,7 +69,7 @@ class CWLTestReport: """Encapsulate relevant test result data for a markdown report.""" def __init__( - self, id: str, category: List[str], entry: str, tool: str, job: Optional[str] + self, id: str, category: list[str], entry: str, tool: str, job: Optional[str] ) -> None: """Initialize a CWLTestReport object.""" self.id = id @@ -124,7 +105,7 @@ def __init__( self.tool = tool self.job = job - def create_test_case(self, test: Dict[str, Any]) -> junit_xml.TestCase: + def create_test_case(self, test: dict[str, Any]) -> junit_xml.TestCase: """Create a jUnit XML test case from this test result.""" doc = test.get("doc", "N/A").strip() if test.get("tags"): @@ -144,7 +125,8 @@ def create_test_case(self, test: Dict[str, Any]) -> junit_xml.TestCase: case.failure_message = self.message return case - def create_report_entry(self, test: Dict[str, Any]) -> CWLTestReport: + def create_report_entry(self, test: dict[str, Any]) -> CWLTestReport: + """Package test result into a CWLTestReport.""" return CWLTestReport( test.get("id", "no-id"), test.get("tags", ["required"]), @@ -154,7 +136,7 @@ def create_report_entry(self, test: Dict[str, Any]) -> CWLTestReport: ) -def _clean_ruamel_list(obj: List[Any]) -> Any: +def _clean_ruamel_list(obj: list[Any]) -> Any: """Entrypoint to transform roundtrip loaded ruamel.yaml to plain objects.""" new_list = [] for entry in obj: @@ -188,10 +170,10 @@ def _clean_ruamel(obj: Any) -> Any: def generate_badges( badgedir: str, - ntotal: Dict[str, int], - npassed: Dict[str, List[CWLTestReport]], - nfailures: Dict[str, List[CWLTestReport]], - nunsupported: Dict[str, List[CWLTestReport]], + ntotal: dict[str, int], + npassed: dict[str, list[CWLTestReport]], + nfailures: dict[str, list[CWLTestReport]], + nunsupported: dict[str, list[CWLTestReport]], ) -> None: """Generate badges with conformance levels.""" os.mkdir(badgedir) @@ -253,7 +235,7 @@ def generate_badges( def get_test_number_by_key( - tests: List[Dict[str, str]], key: str, value: str + tests: list[dict[str, str]], key: str, value: str ) -> Optional[int]: """Retrieve the test index from its name.""" for i, test in enumerate(tests): @@ -262,7 +244,7 @@ def get_test_number_by_key( return None -def load_and_validate_tests(path: str) -> Tuple[Any, Dict[str, Any]]: +def load_and_validate_tests(path: str) -> tuple[Any, dict[str, Any]]: """ Load and validate the given test file against the cwltest schema. @@ -270,7 +252,7 @@ def load_and_validate_tests(path: str) -> Tuple[Any, Dict[str, Any]]: """ schema_resource = files("cwltest").joinpath("cwltest-schema.yml") with schema_resource.open("r", encoding="utf-8") as fp: - cache: Optional[Dict[str, Union[str, Graph, bool]]] = { + cache: Optional[dict[str, Union[str, Graph, bool]]] = { "https://w3id.org/cwl/cwltest/cwltest-schema.yml": fp.read() } ( @@ -289,25 +271,25 @@ def load_and_validate_tests(path: str) -> Tuple[Any, Dict[str, Any]]: tests, metadata = schema_salad.schema.load_and_validate( document_loader, avsc_names, path, True ) - tests = cast(List[Dict[str, Any]], _clean_ruamel_list(tests)) + tests = cast(list[dict[str, Any]], _clean_ruamel_list(tests)) return tests, metadata def parse_results( results: Iterable[TestResult], - tests: List[Dict[str, Any]], + tests: list[dict[str, Any]], suite_name: Optional[str] = None, report: Optional[junit_xml.TestSuite] = None, -) -> Tuple[ +) -> tuple[ int, # total int, # passed int, # failures int, # unsupported - Dict[str, int], # total for each tag - Dict[str, List[CWLTestReport]], # passed for each tag - Dict[str, List[CWLTestReport]], # failures for each tag - Dict[str, List[CWLTestReport]], # unsupported for each tag + dict[str, int], # total for each tag + dict[str, list[CWLTestReport]], # passed for each tag + dict[str, list[CWLTestReport]], # failures for each tag + dict[str, list[CWLTestReport]], # unsupported for each tag Optional[junit_xml.TestSuite], ]: """ @@ -323,10 +305,10 @@ def parse_results( passed = 0 failures = 0 unsupported = 0 - ntotal: Dict[str, int] = Counter() - nfailures: Dict[str, List[CWLTestReport]] = defaultdict(list) - nunsupported: Dict[str, List[CWLTestReport]] = defaultdict(list) - npassed: Dict[str, List[CWLTestReport]] = defaultdict(list) + ntotal: dict[str, int] = Counter() + nfailures: dict[str, list[CWLTestReport]] = defaultdict(list) + nunsupported: dict[str, list[CWLTestReport]] = defaultdict(list) + npassed: dict[str, list[CWLTestReport]] = defaultdict(list) for i, test_result in enumerate(results): test_case = test_result.create_test_case(tests[i]) @@ -379,12 +361,12 @@ def parse_results( def prepare_test_command( tool: str, - args: List[str], - testargs: Optional[List[str]], - test: Dict[str, Any], + args: list[str], + testargs: Optional[list[str]], + test: dict[str, Any], cwd: str, quiet: Optional[bool] = True, -) -> List[str]: +) -> list[str]: """Turn the test into a command line.""" test_command = [tool] test_command.extend(args) @@ -419,9 +401,9 @@ def prepare_test_command( def prepare_test_paths( - test: Dict[str, str], + test: dict[str, str], cwd: str, -) -> Tuple[str, Optional[str]]: +) -> tuple[str, Optional[str]]: """Determine the test path and the tool path.""" cwd = schema_salad.ref_resolver.file_uri(cwd) processfile = test["tool"] @@ -437,13 +419,13 @@ def prepare_test_paths( def run_test_plain( config: CWLTestConfig, - test: Dict[str, str], + test: dict[str, str], test_number: Optional[int] = None, ) -> TestResult: """Plain test runner.""" - out: Dict[str, Any] = {} + out: dict[str, Any] = {} outstr = outerr = "" - test_command: List[str] = [] + test_command: list[str] = [] duration = 0.0 number = "?" @@ -512,12 +494,12 @@ def run_test_plain( logger.error( """Test %i failed: %s""", test_number, - " ".join([shlex.quote(tc) for tc in test_command]), + shlex.join(test_command), ) else: logger.error( """Test failed: %s""", - " ".join([shlex.quote(tc) for tc in test_command]), + shlex.join(test_command), ) logger.error(test.get("doc", "").replace("\n", " ").strip()) if err.returncode == UNSUPPORTED_FEATURE: @@ -539,7 +521,7 @@ def run_test_plain( logger.error( """Test %s failed: %s""", number, - " ".join([shlex.quote(tc) for tc in test_command]), + shlex.join(test_command), ) logger.error(outstr) logger.error("Parse error %s", str(err)) @@ -548,14 +530,14 @@ def run_test_plain( logger.error( """Test %s interrupted: %s""", number, - " ".join([shlex.quote(tc) for tc in test_command]), + shlex.join(test_command), ) raise except json.JSONDecodeError: logger.error( """Test %s failed: %s""", number, - " ".join([shlex.quote(tc) for tc in test_command]), + shlex.join(test_command), ) logger.error(test.get("doc", "").replace("\n", " ").strip()) invalid_json_msg = "Output is not a valid JSON document: '%s'" % outstr @@ -575,7 +557,7 @@ def run_test_plain( logger.error( """Test %s timed out: %s""", number, - " ".join([shlex.quote(tc) for tc in test_command]), + shlex.join(test_command), ) logger.error(test.get("doc", "").replace("\n", " ").strip()) # Kill and re-communicate to get the logs and reap the child, as @@ -611,7 +593,7 @@ def run_test_plain( logger.warning( """Test %s failed: %s""", number, - " ".join([shlex.quote(tc) for tc in test_command]), + shlex.join(test_command), ) logger.warning(test.get("doc", "").replace("\n", " ").strip()) logger.warning("Returned zero but it should be non-zero") @@ -632,7 +614,7 @@ def run_test_plain( logger.warning( """Test %s failed: %s""", number, - " ".join([shlex.quote(tc) for tc in test_command]), + shlex.join(test_command), ) logger.warning(test.get("doc", "").replace("\n", " ").strip()) logger.warning("Compare failure %s", ex) @@ -678,15 +660,15 @@ def load_optional_fsaccess_plugin() -> None: use that to get a filesystem access object that will be used for checking test output. """ - fsaccess_eps: List[EntryPoint] + fsaccess_eps: list[EntryPoint] try: # The interface to importlib.metadata.entry_points() changed - # several times between Python 3.8 and 3.13; the code below + # several times between Python 3.9 and 3.13; the code below # actually works fine on all of them but there's no single # mypy annotation that works across of them. Explicitly cast # it to a consistent type to make mypy shut up. - fsaccess_eps = cast(List[EntryPoint], entry_points()["cwltest.fsaccess"]) # type: ignore [redundant-cast, unused-ignore] + fsaccess_eps = cast(list[EntryPoint], entry_points()["cwltest.fsaccess"]) # type: ignore [redundant-cast, unused-ignore] except KeyError: return diff --git a/docs/requirements.txt b/docs/requirements.txt index 8c1e1f4..e9d8921 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -2,5 +2,4 @@ sphinx >= 2.2 sphinx-rtd-theme==3.0.2 sphinx-autoapi sphinx-autodoc-typehints -typed_ast;python_version<'3.8' sphinxcontrib-autoprogram diff --git a/pyproject.toml b/pyproject.toml index 8daf19f..6d2afc3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,6 @@ classifiers = [ "Operating System :: POSIX", "Operating System :: MacOS :: MacOS X", "Development Status :: 5 - Production/Stable", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -25,7 +24,7 @@ classifiers = [ "Programming Language :: Python :: 3.13", "Typing :: Typed", ] -requires-python = ">=3.8,<3.14" +requires-python = ">=3.9,<3.14" dynamic = ["version", "dependencies"] [project.readme] diff --git a/requirements.txt b/requirements.txt index 16577e2..832cc52 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,3 @@ schema-salad >= 5.0.20200220195218, < 9 junit-xml >= 1.8 pytest >= 7, < 9 defusedxml -importlib_resources>=1.4;python_version<'3.9' diff --git a/tests/test_badgedir.py b/tests/test_badgedir.py index fa421df..e1516d6 100644 --- a/tests/test_badgedir.py +++ b/tests/test_badgedir.py @@ -1,5 +1,5 @@ -import os import json +import os from pathlib import Path from textwrap import dedent diff --git a/tests/test_compare.py b/tests/test_compare.py index b26c074..8149d92 100644 --- a/tests/test_compare.py +++ b/tests/test_compare.py @@ -1,8 +1,9 @@ import os from pathlib import Path -from typing import Any, Dict +from typing import Any import pytest + from cwltest.compare import CompareFail, _compare_directory, _compare_file, compare from .util import get_data @@ -10,7 +11,7 @@ def test_compare_any_success() -> None: expected = "Any" - actual: Dict[str, Any] = {} + actual: dict[str, Any] = {} compare(expected, actual) @@ -385,7 +386,7 @@ def test_compare_file_failure_none() -> None: "class": "File", "checksum": "sha1$7448d8798a4380162d4b56f9b452e2f6f9e24e7b", } - actual: Dict[str, Any] = {} + actual: dict[str, Any] = {} with pytest.raises(CompareFail): compare(expected, actual) @@ -554,7 +555,7 @@ def test_compare_list_failure_type() -> None: "10", ] } - actual: Dict[str, Any] = {"args": {}} + actual: dict[str, Any] = {"args": {}} with pytest.raises(CompareFail): compare(expected, actual) diff --git a/tests/util.py b/tests/util.py index 9394612..937b777 100644 --- a/tests/util.py +++ b/tests/util.py @@ -4,10 +4,9 @@ import os import subprocess # nosec from contextlib import ExitStack +from importlib.resources import as_file, files from pathlib import Path -from typing import List, Optional, Tuple - -from cwltest.utils import as_file, files +from typing import Optional def get_data(filename: str) -> str: @@ -29,8 +28,8 @@ def get_data(filename: str) -> str: def run_with_mock_cwl_runner( - args: List[str], cwl_runner: Optional[str] = None -) -> Tuple[int, str, str]: + args: list[str], cwl_runner: Optional[str] = None +) -> tuple[int, str, str]: """Bind a mock cwlref-runner implementation to cwltest.""" if cwl_runner is None: cwl_runner = get_data("tests/test-data/mock_cwl_runner.py") diff --git a/tox.ini b/tox.ini index 0d54cfb..e2860c0 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,8 @@ [tox] envlist = - py3{8,9,10,11,12,13}-lint, - py3{8,9,10,11,12,13}-unit, - py3{8,9,10,11,12,13}-bandit, + py3{9,10,11,12,13}-lint, + py3{9,10,11,12,13}-unit, + py3{9,10,11,12,13}-bandit, py3{9,10,11,12,13}-mypy, py312-lintreadme, py312-pydocstyle @@ -17,7 +17,6 @@ testpaths = tests [gh-actions] python = - 3.8: py38 3.9: py39 3.10: py310 3.11: py311 @@ -26,12 +25,12 @@ python = [testenv] skipsdist = - py3{8,9,10,11,12,13}-!{unit,mypy,lintreadme} = True + py3{9,10,11,12,13}-!{unit,mypy,lintreadme} = True description = - py3{8,9,10,11,12,13}-unit: Run the unit tests - py3{8,9,10,11,12,13}-lint: Lint the Python code - py3{8,9,10,11,12,13}-bandit: Search for common security issues + py3{9,10,11,12,13}-unit: Run the unit tests + py3{9,10,11,12,13}-lint: Lint the Python code + py3{9,10,11,12,13}-bandit: Search for common security issues py3{9,10,11,12,13}-mypy: Check for type safety py312-pydocstyle: docstring style checker py312-lintreadme: Lint the README.rst->.md conversion @@ -41,36 +40,36 @@ passenv = GITHUB_* deps = - py3{8,9,10,11,12,13}-{unit,mypy}: -rrequirements.txt - py3{8,9,10,11,12,13}-{unit,mypy}: -rtest-requirements.txt - py3{8,9,10,11,12,13}-lint: flake8-bugbear - py3{8,9,10,11,12,13}-lint: black~=23.1 - py3{8,9,10,11,12,13}-bandit: bandit + py3{9,10,11,12,13}-{unit,mypy}: -rrequirements.txt + py3{9,10,11,12,13}-{unit,mypy}: -rtest-requirements.txt + py3{9,10,11,12,13}-lint: flake8-bugbear + py3{9,10,11,12,13}-lint: black~=23.1 + py3{9,10,11,12,13}-bandit: bandit py3{9,10,11,12,13}-mypy: -rmypy-requirements.txt set_env = - py3{8,3,10,11,12,13}-unit: LC_ALL = C.UTF-8 + py3{9,10,11,12,13}-unit: LC_ALL = C.UTF-8 COV_CORE_SOURCE=cwltest COV_CORE_CONFIG={toxinidir}/.coveragerc COV_CORE_DATAFILE={toxinidir}/.coverage.eager commands = - py3{8,9,10,11,12,13}-unit: python -m pip install -U pip setuptools wheel - py3{8,9,10,11,12,13}-unit: python -m pytest --cov --cov-config={toxinidir}/.coveragerc --cov-append {posargs} - py3{8,9,10,11,12,13}-unit: coverage xml - py3{8,9,10,11,12,13}-bandit: bandit --recursive cwltest - py3{8,9,10,11,12,13}-lint: make flake8 - py3{8,9,10,11,12,13}-lint: make format-check + py3{9,10,11,12,13}-unit: python -m pip install -U pip setuptools wheel + py3{9,10,11,12,13}-unit: python -m pytest --cov --cov-config={toxinidir}/.coveragerc --cov-append {posargs} + py3{9,10,11,12,13}-unit: coverage xml + py3{9,10,11,12,13}-bandit: bandit --recursive cwltest + py3{9,10,11,12,13}-lint: make flake8 + py3{9,10,11,12,13}-lint: make format-check py3{9,10,11,12,13}-mypy: make mypy allowlist_externals = - py3{8,9,10,11,12,13}-lint: flake8 - py3{8,9,10,11,12,13}-lint: black - py3{8,9,10,11,12,13}-{mypy,shellcheck,lint,unit}: make + py3{9,10,11,12,13}-lint: flake8 + py3{9,10,11,12,13}-lint: black + py3{9,10,11,12,13}-{mypy,shellcheck,lint,unit}: make skip_install = - py3{8,9,10,11,12,13}-lint: true - py3{8,9,10,11,12,13}-bandit: true + py3{9,10,11,12,13}-lint: true + py3{9,10,11,12,13}-bandit: true [testenv:py312-pydocstyle] From 7e919f62efa71c4ed7d76829c69b5e76871befbc Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 14 Mar 2025 14:58:07 +0100 Subject: [PATCH 146/165] Improve test coverage --- tests/test_numeric_id.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/test_numeric_id.py diff --git a/tests/test_numeric_id.py b/tests/test_numeric_id.py new file mode 100644 index 0000000..64a2128 --- /dev/null +++ b/tests/test_numeric_id.py @@ -0,0 +1,15 @@ +from os import linesep as n + +from .util import get_data, run_with_mock_cwl_runner + + +def test_include_by_number() -> None: + args = [ + "--test", + get_data("tests/test-data/exclude-tags.yml"), + "-n1", + ] + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + assert f"[1/3] opt-error1: Test with label{n}" in stderr + assert "opt-error2" not in stderr + assert "opt-error3" not in stderr From d565670410e42576313c62d0bb1b511e00dac9ee Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 14 Mar 2025 15:06:03 +0100 Subject: [PATCH 147/165] --show-tags: sort the output & add a test --- cwltest/main.py | 2 +- tests/test_categories.py | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/cwltest/main.py b/cwltest/main.py index 92fe672..c38efd2 100644 --- a/cwltest/main.py +++ b/cwltest/main.py @@ -165,7 +165,7 @@ def main() -> int: for t in tests: ts = t.get("tags", []) alltags |= set(ts) - for tag in alltags: + for tag in sorted(alltags): print(tag) return 0 diff --git a/tests/test_categories.py b/tests/test_categories.py index ceb2f3b..bc948f9 100644 --- a/tests/test_categories.py +++ b/tests/test_categories.py @@ -93,3 +93,23 @@ def test_category_in_junit_xml(tmp_path: Path) -> None: Element, cast(Element, root.find("testsuite")).find("testcase") ).attrib["class"] assert category == "js, init_work_dir" + + +def test_list_all_tags() -> None: + args = [ + "--test", + schema_salad.ref_resolver.file_uri( + get_data("tests/test-data/conformance_test_v1.2.cwltest.yaml") + ), + "--show-tags", + ] + error_code, stdout, stderr = run_with_mock_cwl_runner(args) + assert error_code == 0, stderr + assert ( + stdout + == """command_line_tool +expression_tool +inline_javascript +required +""" + ) From 24da941a3551e5bed7ceee455c316a9d1d0869c9 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 14 Feb 2025 14:59:38 +0100 Subject: [PATCH 148/165] simplify some imports --- cwltest/plugin.py | 16 ++++++---------- tests/test_plugin.py | 22 ++++++++++------------ 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/cwltest/plugin.py b/cwltest/plugin.py index c780504..006b11a 100644 --- a/cwltest/plugin.py +++ b/cwltest/plugin.py @@ -17,11 +17,7 @@ from cwltest.compare import CompareFail, compare if TYPE_CHECKING: - from _pytest._code.code import ExceptionInfo, TracebackStyle - from _pytest.config import Config - from _pytest.config import Config as PytestConfig - from _pytest.config import PytestPluginManager - from _pytest.config.argparsing import Parser as PytestParser + from _pytest._code.code import TracebackStyle from _pytest.nodes import Node from pluggy import HookCaller @@ -36,7 +32,7 @@ def __call__( ... -def _get_comma_separated_option(config: "Config", name: str) -> list[str]: +def _get_comma_separated_option(config: pytest.Config, name: str) -> list[str]: options = config.getoption(name) if options is None: return [] @@ -195,7 +191,7 @@ def runtest(self) -> None: def repr_failure( self, - excinfo: "ExceptionInfo[BaseException]", + excinfo: pytest.ExceptionInfo[BaseException], style: Optional["TracebackStyle"] = None, ) -> str: """ @@ -359,7 +355,7 @@ def collect(self) -> Iterator[CWLItem]: ] -def pytest_addoption(parser: "PytestParser") -> None: +def pytest_addoption(parser: pytest.Parser) -> None: """Add our options to the pytest command line.""" for entry in __OPTIONS: parser.addoption(entry[0], **entry[1]) @@ -387,7 +383,7 @@ def pytest_collect_file( return None -def pytest_configure(config: "PytestConfig") -> None: +def pytest_configure(config: pytest.Config) -> None: """Store the raw tests and the test results.""" cwl_results: list[tuple[dict[str, Any], utils.TestResult]] = [] config.cwl_results = cwl_results # type: ignore[attr-defined] @@ -417,7 +413,7 @@ def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None: utils.generate_badges(cwl_badgedir, ntotal, npassed, nfailures, nunsupported) -def pytest_addhooks(pluginmanager: "PytestPluginManager") -> None: +def pytest_addhooks(pluginmanager: pytest.PytestPluginManager) -> None: """Register our cwl hooks.""" from cwltest import hooks diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 4bc4a69..5820831 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -1,12 +1,10 @@ import os import shutil from pathlib import Path -from typing import TYPE_CHECKING -from .util import get_data +import pytest -if TYPE_CHECKING: - from _pytest.pytester import Pytester +from .util import get_data def _load_v1_0_dir(path: Path) -> None: @@ -20,7 +18,7 @@ def _load_v1_0_dir(path: Path) -> None: shutil.copy(get_data("tests/test-data/v1.0/args.py"), inner_dir) -def test_include(pytester: "Pytester") -> None: +def test_include(pytester: pytest.Pytester) -> None: """Test the pytest plugin using cwltool as cwl-runner.""" path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") shutil.copy( @@ -36,7 +34,7 @@ def test_include(pytester: "Pytester") -> None: result.assert_outcomes(passed=1, skipped=1) -def test_exclude(pytester: "Pytester") -> None: +def test_exclude(pytester: pytest.Pytester) -> None: """Test the pytest plugin using cwltool as cwl-runner.""" path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") shutil.copy( @@ -52,7 +50,7 @@ def test_exclude(pytester: "Pytester") -> None: result.assert_outcomes(passed=0, skipped=2) -def test_tags(pytester: "Pytester") -> None: +def test_tags(pytester: pytest.Pytester) -> None: """Test the pytest plugin using cwltool as cwl-runner.""" path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") shutil.copy( @@ -65,7 +63,7 @@ def test_tags(pytester: "Pytester") -> None: result.assert_outcomes(passed=1, skipped=1) -def test_exclude_tags(pytester: "Pytester") -> None: +def test_exclude_tags(pytester: pytest.Pytester) -> None: """Test the pytest plugin using cwltool as cwl-runner.""" path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") shutil.copy( @@ -81,7 +79,7 @@ def test_exclude_tags(pytester: "Pytester") -> None: result.assert_outcomes(skipped=2) -def test_badgedir(pytester: "Pytester") -> None: +def test_badgedir(pytester: pytest.Pytester) -> None: """Test the pytest plugin creates the badges directory.""" path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") shutil.copy( @@ -95,7 +93,7 @@ def test_badgedir(pytester: "Pytester") -> None: assert os.path.exists("cwl-badges") -def test_no_label(pytester: "Pytester") -> None: +def test_no_label(pytester: pytest.Pytester) -> None: """Test the pytest plugin correctly extracts test names from the id field when label is missing.""" path = pytester.copy_example("conformance_test_v1.2.cwltest.yaml") shutil.copy( @@ -108,7 +106,7 @@ def test_no_label(pytester: "Pytester") -> None: result.assert_outcomes(passed=2, skipped=1) -def test_cwltool_hook(pytester: "Pytester") -> None: +def test_cwltool_hook(pytester: pytest.Pytester) -> None: """Test the pytest plugin using cwltool as cwl-runner.""" path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") shutil.copy( @@ -119,7 +117,7 @@ def test_cwltool_hook(pytester: "Pytester") -> None: result.assert_outcomes(passed=2) -def test_no_hook(pytester: "Pytester") -> None: +def test_no_hook(pytester: pytest.Pytester) -> None: """Test the pytest plugin using the default cwl-runner.""" path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") _load_v1_0_dir(path) From 1117ba59a99f2752c59bdd1526bb3ef98cadb33b Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 14 Feb 2025 15:00:06 +0100 Subject: [PATCH 149/165] fix badge generation for test with int IDs. --- cwltest/utils.py | 14 +++++++++----- tests/test_plugin.py | 11 ++++++++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/cwltest/utils.py b/cwltest/utils.py index 33aee52..a14ae7a 100644 --- a/cwltest/utils.py +++ b/cwltest/utils.py @@ -69,7 +69,12 @@ class CWLTestReport: """Encapsulate relevant test result data for a markdown report.""" def __init__( - self, id: str, category: list[str], entry: str, tool: str, job: Optional[str] + self, + id: Union[int, str], + category: list[str], + entry: str, + tool: str, + job: Optional[str], ) -> None: """Initialize a CWLTestReport object.""" self.id = id @@ -199,10 +204,9 @@ def generate_badges( with open(f"{badgedir}/{t}.md", "w") as out: print(f"# `{t}` tests", file=out) - print("## List of passed tests", file=out) for e in npassed[t]: - base = f"[{shortname(e.id)}]({e.entry})" + base = f"[{shortname(str(e.id))}]({e.entry})" tool = f"[tool]({e.tool})" if e.job: arr = [tool, f"[job]({e.job})"] @@ -213,7 +217,7 @@ def generate_badges( print("## List of failed tests", file=out) for e in nfailures[t]: - base = f"[{shortname(e.id)}]({e.entry})" + base = f"[{shortname(str(e.id))}]({e.entry})" tool = f"[tool]({e.tool})" if e.job: arr = [tool, f"[job]({e.job})"] @@ -224,7 +228,7 @@ def generate_badges( print("## List of unsupported tests", file=out) for e in nunsupported[t]: - base = f"[{shortname(e.id)}]({e.entry})" + base = f"[{shortname(str(e.id))}]({e.entry})" tool = f"[tool]({e.tool})" if e.job: arr = [tool, f"[job]({e.job})"] diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 5820831..12c72ab 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -86,11 +86,16 @@ def test_badgedir(pytester: pytest.Pytester) -> None: get_data("tests/test-data/cwltool-conftest.py"), path.parent / "conftest.py" ) _load_v1_0_dir(path) - assert not os.path.exists("cwl-badges") + badge_path = path.parent / "cwl-badges" + assert not badge_path.exists() pytester.runpytest( - "-k", "conformance_test_v1.0.cwltest.yml", "--cwl-badgedir", "cwl-badges" + "-k", "conformance_test_v1.0.cwltest.yml", "--cwl-badgedir", str(badge_path) ) - assert os.path.exists("cwl-badges") + assert badge_path.exists() + assert (badge_path / "command_line_tool.json").exists() + assert (badge_path / "command_line_tool.md").exists() + assert (badge_path / "required.json").exists() + assert (badge_path / "required.md").exists() def test_no_label(pytester: pytest.Pytester) -> None: From 7fc69d6c80598844af21449206f56e8324f8f33c Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Sat, 1 Mar 2025 16:15:52 +0100 Subject: [PATCH 150/165] support xdist via pickling the per-worker results --- cwltest/plugin.py | 59 ++++++++++++++++++++++++++++++++++++++------ tests/test_plugin.py | 28 ++++++++++++++++++++- 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/cwltest/plugin.py b/cwltest/plugin.py index 006b11a..5dabf9e 100644 --- a/cwltest/plugin.py +++ b/cwltest/plugin.py @@ -3,6 +3,7 @@ import argparse import json import os +import pickle # nosec import time import traceback from collections.abc import Iterator @@ -389,15 +390,59 @@ def pytest_configure(config: pytest.Config) -> None: config.cwl_results = cwl_results # type: ignore[attr-defined] -def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None: +def _zip_results( + cwl_results: list[tuple[dict[str, Any], utils.TestResult]], +) -> tuple[list[dict[str, Any]], list[utils.TestResult]]: + tests, results = (list(item) for item in zip(*cwl_results)) + return tests, results + + +def pytest_sessionfinish(session: pytest.Session) -> None: """Generate badges.""" + cwl_badgedir = session.config.getoption("cwl_badgedir") + if not cwl_badgedir: + return + cwl_results = cast( list[tuple[dict[str, Any], utils.TestResult]], - getattr(session.config, "cwl_results", None), + session.config.cwl_results, # type: ignore[attr-defined] ) - if not cwl_results: - return - tests, results = (list(item) for item in zip(*cwl_results)) + + if session.config.pluginmanager.has_plugin("xdist"): + import xdist # type: ignore[import-untyped] + + directory = cast( + pytest.TempPathFactory, + session.config._tmp_path_factory, # type: ignore[attr-defined] + ).getbasetemp() + if xdist.is_xdist_worker(session): + if not cwl_results: + return + pickle_filename = f"cwltest_{xdist.get_xdist_worker_id(session)}.pickle" + with (directory.parent / pickle_filename).open("wb") as handle: + pickle.dump( + _zip_results(cwl_results), handle, protocol=pickle.HIGHEST_PROTOCOL + ) + return + + if xdist.is_xdist_controller(session): + tests: list[dict[str, Any]] = [] + results: list[utils.TestResult] = [] + for pickle_filepath in directory.glob("cwltest_*"): + with pickle_filepath.open("rb") as handle: + new_tests, new_results = pickle.load(handle) # nosec + tests.extend(new_tests) + results.extend(new_results) + else: + if not cwl_results: + return + tests, results = _zip_results(cwl_results) + + else: + if not cwl_results: + return + tests, results = _zip_results(cwl_results) + ( total, passed, @@ -409,8 +454,8 @@ def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None: nunsupported, _, ) = utils.parse_results(results, tests) - if cwl_badgedir := session.config.getoption("cwl_badgedir"): - utils.generate_badges(cwl_badgedir, ntotal, npassed, nfailures, nunsupported) + + utils.generate_badges(cwl_badgedir, ntotal, npassed, nfailures, nunsupported) def pytest_addhooks(pluginmanager: pytest.PytestPluginManager) -> None: diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 12c72ab..d0e3d0c 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -88,9 +88,35 @@ def test_badgedir(pytester: pytest.Pytester) -> None: _load_v1_0_dir(path) badge_path = path.parent / "cwl-badges" assert not badge_path.exists() - pytester.runpytest( + result = pytester.runpytest_inprocess( "-k", "conformance_test_v1.0.cwltest.yml", "--cwl-badgedir", str(badge_path) ) + result.assert_outcomes(passed=2) + assert badge_path.exists() + assert (badge_path / "command_line_tool.json").exists() + assert (badge_path / "command_line_tool.md").exists() + assert (badge_path / "required.json").exists() + assert (badge_path / "required.md").exists() + + +def test_badgedir_xdist(pytester: pytest.Pytester) -> None: + """Test the pytest plugin creates the badges directory even with xdist.""" + path = pytester.copy_example("conformance_test_v1.0.cwltest.yml") + shutil.copy( + get_data("tests/test-data/cwltool-conftest.py"), path.parent / "conftest.py" + ) + _load_v1_0_dir(path) + badge_path = path.parent / "cwl-badges" + assert not badge_path.exists() + result = pytester.runpytest_inprocess( + "-n", + "2", + "-k", + "conformance_test_v1.0.cwltest.yml", + "--cwl-badgedir", + str(badge_path), + ) + result.assert_outcomes(passed=2) assert badge_path.exists() assert (badge_path / "command_line_tool.json").exists() assert (badge_path / "command_line_tool.md").exists() From 2949b84bc50a0c5eb382f9db57e65d30d62f6a1c Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Fri, 14 Mar 2025 16:25:37 +0100 Subject: [PATCH 151/165] bump version to 2.6 due to dropped support for Python 3.8; and fixed badge generation --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9abf584..6bcc2a5 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ PYSOURCES=$(wildcard ${MODULE}/**.py tests/*.py) DEVPKGS=-rdev-requirements.txt -rtest-requirements.txt -rmypy-requirements.txt DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage pydocstyle sloccount \ python-flake8 python-mock shellcheck -VERSION=2.5.$(shell TZ=UTC git log --first-parent --max-count=1 \ +VERSION=2.6.$(shell TZ=UTC git log --first-parent --max-count=1 \ --format=format:%cd --date=format-local:%Y%m%d%H%M%S) ## all : default task (install in dev mode) From a1c3ee13d9196ddf9cde7307ad39838b4a383f04 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 00:02:44 +0000 Subject: [PATCH 152/165] Bump mypy from 1.15.0 to 1.16.0 Bumps [mypy](https://github.com/python/mypy) from 1.15.0 to 1.16.0. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.15.0...v1.16.0) --- updated-dependencies: - dependency-name: mypy dependency-version: 1.16.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 1327dd1..f42c273 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.15.0 +mypy==1.16.0 pytest >= 8.3, < 9 types-setuptools types-requests From 5c72297ceacdaf0d54e757ca1e201238ac0e1e4c Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Fri, 30 May 2025 12:14:48 +0100 Subject: [PATCH 153/165] Fix new type annotation errors from mypy 1.16.0 --- tests/test_categories.py | 10 ++++------ tests/test_short_names.py | 10 ++++------ tests/test_timeout.py | 22 +++++++--------------- 3 files changed, 15 insertions(+), 27 deletions(-) diff --git a/tests/test_categories.py b/tests/test_categories.py index bc948f9..ba08407 100644 --- a/tests/test_categories.py +++ b/tests/test_categories.py @@ -3,8 +3,6 @@ from os import linesep as n from os import sep as p from pathlib import Path -from typing import cast -from xml.etree.ElementTree import Element import defusedxml.ElementTree as ET import schema_salad.ref_resolver @@ -88,10 +86,10 @@ def test_category_in_junit_xml(tmp_path: Path) -> None: ] run_with_mock_cwl_runner(args) tree = ET.parse(junit_xml_report) - root = tree.getroot() - category = cast( - Element, cast(Element, root.find("testsuite")).find("testcase") - ).attrib["class"] + assert (root := tree.getroot()) is not None + assert (testsuite_el := root.find("testsuite")) is not None + assert (testcase_el := testsuite_el.find("testcase")) is not None + category = testcase_el.attrib["class"] assert category == "js, init_work_dir" diff --git a/tests/test_short_names.py b/tests/test_short_names.py index da87b6c..fbd2f19 100644 --- a/tests/test_short_names.py +++ b/tests/test_short_names.py @@ -1,7 +1,5 @@ from os import linesep as n from pathlib import Path -from typing import cast -from xml.etree.ElementTree import Element import defusedxml.ElementTree as ET @@ -49,8 +47,8 @@ def test_short_name_in_junit_xml(tmp_path: Path) -> None: ] run_with_mock_cwl_runner(args) tree = ET.parse(junit_xml_report) - root = tree.getroot() - category = cast( - Element, cast(Element, root.find("testsuite")).find("testcase") - ).attrib["file"] + assert (root := tree.getroot()) is not None + assert (testsuite_el := root.find("testsuite")) is not None + assert (testcase_el := testsuite_el.find("testcase")) is not None + category = testcase_el.attrib["file"] assert category == "opt-error" diff --git a/tests/test_timeout.py b/tests/test_timeout.py index bc01636..ad85219 100644 --- a/tests/test_timeout.py +++ b/tests/test_timeout.py @@ -1,7 +1,5 @@ import os from pathlib import Path -from typing import cast -from xml.etree.ElementTree import Element import defusedxml.ElementTree as ET import schema_salad.ref_resolver @@ -31,20 +29,14 @@ def test_timeout_stderr_stdout(tmp_path: Path) -> None: assert "Test 1 timed out" in stderr tree = ET.parse(junit_xml_report) try: - root = tree.getroot() - timeout_text = cast( - Element, - cast(Element, cast(Element, root.find("testsuite")).find("testcase")).find( - "failure" - ), - ).text - timeout_stderr = cast( - Element, - cast(Element, cast(Element, root.find("testsuite")).find("testcase")).find( - "system-err" - ), - ).text + assert (root := tree.getroot()) is not None + assert (testsuite_el := root.find("testsuite")) is not None + assert (testcase_el := testsuite_el.find("testcase")) is not None + assert (failure_el := testcase_el.find("failure")) is not None + timeout_text = failure_el.text assert timeout_text is not None and "Test timed out" in timeout_text + assert (system_err_el := testcase_el.find("system-err")) is not None + timeout_stderr = system_err_el.text assert timeout_stderr is not None and "timeout stderr" in timeout_stderr except AttributeError as e: print(junit_xml_report.read_text()) From 54a9033f442d525f48d6fb8906f9c4d873a98842 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 02:00:37 +0000 Subject: [PATCH 154/165] Bump mypy from 1.16.0 to 1.16.1 Bumps [mypy](https://github.com/python/mypy) from 1.16.0 to 1.16.1. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.16.0...v1.16.1) --- updated-dependencies: - dependency-name: mypy dependency-version: 1.16.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index f42c273..df3e2e8 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.16.0 +mypy==1.16.1 pytest >= 8.3, < 9 types-setuptools types-requests From bbde3154a29a57322224075056f5e8c9f5e33a6e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 03:39:41 +0000 Subject: [PATCH 155/165] Bump mypy from 1.16.1 to 1.17.0 Bumps [mypy](https://github.com/python/mypy) from 1.16.1 to 1.17.0. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.16.1...v1.17.0) --- updated-dependencies: - dependency-name: mypy dependency-version: 1.17.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index df3e2e8..f2a4e19 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.16.1 +mypy==1.17.0 pytest >= 8.3, < 9 types-setuptools types-requests From 3f345a4de7788144d76fe0803258529af80dd7c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 00:17:09 +0000 Subject: [PATCH 156/165] Bump mypy from 1.17.0 to 1.17.1 Bumps [mypy](https://github.com/python/mypy) from 1.17.0 to 1.17.1. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.17.0...v1.17.1) --- updated-dependencies: - dependency-name: mypy dependency-version: 1.17.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index f2a4e19..ddb4b10 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.17.0 +mypy==1.17.1 pytest >= 8.3, < 9 types-setuptools types-requests From 8798950a1938f1eb9bab679efed993a9fb73107d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 10:21:51 +0000 Subject: [PATCH 157/165] Update setuptools-scm requirement from <9,>=8.0.4 to >=8.0.4,<10 Updates the requirements on [setuptools-scm](https://github.com/pypa/setuptools-scm) to permit the latest version. - [Release notes](https://github.com/pypa/setuptools-scm/releases) - [Changelog](https://github.com/pypa/setuptools-scm/blob/main/CHANGELOG.md) - [Commits](https://github.com/pypa/setuptools-scm/compare/v8.0.4...v9.1.1) --- updated-dependencies: - dependency-name: setuptools-scm dependency-version: 9.1.1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6d2afc3..0cf0bd5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [build-system] requires = [ "setuptools>=61.2", - "setuptools_scm>=8.0.4,<9", + "setuptools_scm>=8.0.4,<10", ] build-backend = "setuptools.build_meta" From e12e3657bc6849fea6faf54f06164f1ef118c52d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:35:23 +0000 Subject: [PATCH 158/165] Bump actions/checkout from 4 to 5 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci-tests.yml | 6 +++--- .github/workflows/codeql-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 7875d79..7972b7f 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -30,7 +30,7 @@ jobs: TOXENV: ${{ format('py{0}{1}-{2}', matrix.py-ver-major, matrix.py-ver-minor, matrix.step) }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 @@ -81,7 +81,7 @@ jobs: TOXENV: ${{ format('py312-{0}', matrix.step) }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 @@ -113,7 +113,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 47cc649..e1a42c8 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. From 6028c3c794d8936ab63f5888637528bef54af9b5 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Mon, 18 Aug 2025 01:43:17 +0100 Subject: [PATCH 159/165] Support Python 3.14.x --- .github/workflows/ci-tests.yml | 15 ++++---- pyproject.toml | 3 +- tox.ini | 65 +++++++++++++++++----------------- 3 files changed, 44 insertions(+), 39 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 7972b7f..b2b3a91 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -22,7 +22,7 @@ jobs: matrix: # The README.rst file mentions the versions tested, please update it as well py-ver-major: [3] - py-ver-minor: [9, 10, 11, 12, 13] + py-ver-minor: [9, 10, 11, 12, 13, 14] step: [lint, unit, mypy, bandit] env: @@ -50,6 +50,9 @@ jobs: pip install -U pip setuptools wheel pip install "tox>4,<5" "tox-gh-actions>3" + - name: install dev libraries + run: sudo apt-get install -y libxml2-dev libxslt-dev + - name: MyPy cache if: ${{ matrix.step == 'mypy' }} uses: actions/cache@v4 @@ -70,15 +73,15 @@ jobs: tox-style: name: CI linters via Tox - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: matrix: step: [lintreadme, pydocstyle] env: - py-semver: "3.12" - TOXENV: ${{ format('py312-{0}', matrix.step) }} + py-semver: "3.13" + TOXENV: ${{ format('py313-{0}', matrix.step) }} steps: - uses: actions/checkout@v5 @@ -110,7 +113,7 @@ jobs: release_test: name: cwltest release test - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v5 @@ -118,7 +121,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.12" + python-version: "3.13" cache: pip cache-dependency-path: | requirements.txt diff --git a/pyproject.toml b/pyproject.toml index 0cf0bd5..da2775f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,9 +22,10 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Typing :: Typed", ] -requires-python = ">=3.9,<3.14" +requires-python = ">=3.9,<3.15" dynamic = ["version", "dependencies"] [project.readme] diff --git a/tox.ini b/tox.ini index e2860c0..5bb9fae 100644 --- a/tox.ini +++ b/tox.ini @@ -1,9 +1,9 @@ [tox] envlist = - py3{9,10,11,12,13}-lint, - py3{9,10,11,12,13}-unit, - py3{9,10,11,12,13}-bandit, - py3{9,10,11,12,13}-mypy, + py3{9,10,11,12,13,14}-lint, + py3{9,10,11,12,13,14}-unit, + py3{9,10,11,12,13,14}-bandit, + py3{9,10,11,12,13,14}-mypy, py312-lintreadme, py312-pydocstyle @@ -22,57 +22,58 @@ python = 3.11: py311 3.12: py312 3.13: py313 + 3.14: py314 [testenv] skipsdist = - py3{9,10,11,12,13}-!{unit,mypy,lintreadme} = True + py3{9,10,11,12,13,14}-!{unit,mypy,lintreadme} = True description = - py3{9,10,11,12,13}-unit: Run the unit tests - py3{9,10,11,12,13}-lint: Lint the Python code - py3{9,10,11,12,13}-bandit: Search for common security issues - py3{9,10,11,12,13}-mypy: Check for type safety - py312-pydocstyle: docstring style checker - py312-lintreadme: Lint the README.rst->.md conversion + py3{9,10,11,12,13,14}-unit: Run the unit tests + py3{9,10,11,12,13,14}-lint: Lint the Python code + py3{9,10,11,12,13,14}-bandit: Search for common security issues + py3{9,10,11,12,13,14}-mypy: Check for type safety + py313-pydocstyle: docstring style checker + py313-lintreadme: Lint the README.rst->.md conversion passenv = CI GITHUB_* deps = - py3{9,10,11,12,13}-{unit,mypy}: -rrequirements.txt - py3{9,10,11,12,13}-{unit,mypy}: -rtest-requirements.txt - py3{9,10,11,12,13}-lint: flake8-bugbear - py3{9,10,11,12,13}-lint: black~=23.1 - py3{9,10,11,12,13}-bandit: bandit - py3{9,10,11,12,13}-mypy: -rmypy-requirements.txt + py3{9,10,11,12,13,14}-{unit,mypy}: -rrequirements.txt + py3{9,10,11,12,13,14}-{unit,mypy}: -rtest-requirements.txt + py3{9,10,11,12,13,14}-lint: flake8-bugbear + py3{9,10,11,12,13,14}-lint: black~=23.1 + py3{9,10,11,12,13,14}-bandit: bandit + py3{9,10,11,12,13,14}-mypy: -rmypy-requirements.txt set_env = - py3{9,10,11,12,13}-unit: LC_ALL = C.UTF-8 + py3{9,10,11,12,13,14}-unit: LC_ALL = C.UTF-8 COV_CORE_SOURCE=cwltest COV_CORE_CONFIG={toxinidir}/.coveragerc COV_CORE_DATAFILE={toxinidir}/.coverage.eager commands = - py3{9,10,11,12,13}-unit: python -m pip install -U pip setuptools wheel - py3{9,10,11,12,13}-unit: python -m pytest --cov --cov-config={toxinidir}/.coveragerc --cov-append {posargs} - py3{9,10,11,12,13}-unit: coverage xml - py3{9,10,11,12,13}-bandit: bandit --recursive cwltest - py3{9,10,11,12,13}-lint: make flake8 - py3{9,10,11,12,13}-lint: make format-check - py3{9,10,11,12,13}-mypy: make mypy + py3{9,10,11,12,13,14}-unit: python -m pip install -U pip setuptools wheel + py3{9,10,11,12,13,14}-unit: python -m pytest --cov --cov-config={toxinidir}/.coveragerc --cov-append {posargs} + py3{9,10,11,12,13,14}-unit: coverage xml + py3{9,10,11,12,13,14}-bandit: bandit --recursive cwltest + py3{9,10,11,12,13,14}-lint: make flake8 + py3{9,10,11,12,13,14}-lint: make format-check + py3{9,10,11,12,13,14}-mypy: make mypy allowlist_externals = - py3{9,10,11,12,13}-lint: flake8 - py3{9,10,11,12,13}-lint: black - py3{9,10,11,12,13}-{mypy,shellcheck,lint,unit}: make + py3{9,10,11,12,13,14}-lint: flake8 + py3{9,10,11,12,13,14}-lint: black + py3{9,10,11,12,13,14}-{mypy,shellcheck,lint,unit}: make skip_install = - py3{9,10,11,12,13}-lint: true - py3{9,10,11,12,13}-bandit: true + py3{9,10,11,12,13,14}-lint: true + py3{9,10,11,12,13,14}-bandit: true -[testenv:py312-pydocstyle] +[testenv:py313-pydocstyle] allowlist_externals = make commands = make diff_pydocstyle_report deps = @@ -80,7 +81,7 @@ deps = diff-cover skip_install = true -[testenv:py312-lintreadme] +[testenv:py313-lintreadme] description = Lint the README.rst->.md conversion commands = python -m build --outdir dist From 88e9e0787feeb482e3a799ec1a73a5f18695f52a Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Mon, 18 Aug 2025 02:08:57 +0100 Subject: [PATCH 160/165] README: note Python 3.14 support --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 7c17c99..9a5a295 100644 --- a/README.rst +++ b/README.rst @@ -32,7 +32,7 @@ This is a testing tool for checking the output of Tools and Workflows described with the Common Workflow Language. Among other uses, it is used to run the CWL conformance tests. -This is written and tested for Python 3.9, 3.10, 3.11, 3.12, and 3.13. +This is written and tested for Python 3.9, 3.10, 3.11, 3.12, 3.13, and 3.14 .. contents:: Table of Contents :local: From ea243c20b4361f97bce80ccd1635751879c573d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 00:05:35 +0000 Subject: [PATCH 161/165] Bump actions/setup-python from 5 to 6 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/setup-python dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci-tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index b2b3a91..bbda8ef 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -35,7 +35,7 @@ jobs: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ env.py-semver }} allow-prereleases: true @@ -89,7 +89,7 @@ jobs: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ env.py-semver }} cache: pip @@ -119,7 +119,7 @@ jobs: - uses: actions/checkout@v5 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.13" cache: pip From 9d0631371cd4be4227302eac53874d0513e489cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Sep 2025 00:02:09 +0000 Subject: [PATCH 162/165] Bump mypy from 1.17.1 to 1.18.1 Bumps [mypy](https://github.com/python/mypy) from 1.17.1 to 1.18.1. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.17.1...v1.18.1) --- updated-dependencies: - dependency-name: mypy dependency-version: 1.18.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index ddb4b10..8619669 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.17.1 +mypy==1.18.1 pytest >= 8.3, < 9 types-setuptools types-requests From 8cb1be0edf7ecffab5886708f606da207652b3ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 00:01:53 +0000 Subject: [PATCH 163/165] Bump mypy from 1.18.1 to 1.18.2 Bumps [mypy](https://github.com/python/mypy) from 1.18.1 to 1.18.2. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.18.1...v1.18.2) --- updated-dependencies: - dependency-name: mypy dependency-version: 1.18.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 8619669..f2e4771 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.18.1 +mypy==1.18.2 pytest >= 8.3, < 9 types-setuptools types-requests From 062da72c21fcc644d669e827cf014580fa747b2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 00:01:58 +0000 Subject: [PATCH 164/165] Update black requirement from ~=25.1 to ~=25.9 Updates the requirements on [black](https://github.com/psf/black) to permit the latest version. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/25.1.0...25.9.0) --- updated-dependencies: - dependency-name: black dependency-version: 25.9.0 dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index c5c27be..2373021 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,5 @@ diff_cover -black ~= 25.1 +black ~= 25.9 pylint pep257 pydocstyle From 22cd6f6a7a4ae49d9c8b801d539e0690a44bdeba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Oct 2025 00:06:33 +0000 Subject: [PATCH 165/165] Bump github/codeql-action from 3 to 4 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v3...v4) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e1a42c8..6ba449c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -32,9 +32,9 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: python - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4