Skip to content

Commit

Permalink
code: drop Python 3.6-3.7 support
Browse files Browse the repository at this point in the history
  • Loading branch information
mr-c committed Aug 8, 2023
1 parent 974ba06 commit 2989ba9
Show file tree
Hide file tree
Showing 44 changed files with 91 additions and 1,932 deletions.
11 changes: 2 additions & 9 deletions .github/workflows/ci-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,12 @@ jobs:

tox:
name: Tox
runs-on: ubuntu-20.04 # 22.04 doesn't support Python 3.6
runs-on: ubuntu-22.04
strategy:
matrix:
py-ver-major: [3]
py-ver-minor: [6, 8, 9, 10, 11]
py-ver-minor: [8, 9, 10, 11]
step: [lint, unit, bandit, mypy]
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) }}
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Style guide:
- PEP-8 (as implemented by the `black` code formatting tool)
- Python 3.6+ compatible code
- Python 3.8+ compatible code
- PEP-484 type hints

The development is done using `git`, we encourage you to get familiar with it.
Expand Down
15 changes: 3 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ MODULE=cwltool
# `SHELL=bash` doesn't work for some, so don't use BASH-isms like
# `[[` conditional expressions.
PYSOURCES=$(wildcard ${MODULE}/**.py cwltool/cwlprov/*.py tests/*.py) setup.py
DEVPKGS=diff_cover pylint pep257 pydocstyle 'tox<4' tox-pyenv \
DEVPKGS=diff_cover pylint pep257 pydocstyle 'tox<4' tox-pyenv auto-walrus \
isort wheel autoflake pyupgrade bandit -rlint-requirements.txt\
-rtest-requirements.txt -rmypy-requirements.txt -rdocs/requirements.txt
DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage pydocstyle sloccount \
Expand Down Expand Up @@ -191,16 +191,6 @@ mypy: $(PYSOURCES)
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 python -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 python -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 $^


mypyc: $(PYSOURCES)
MYPYPATH=mypy-stubs CWLTOOL_USE_MYPYC=1 pip install --verbose -e . \
&& pytest -rs -vv ${PYTEST_EXTRA}
Expand All @@ -210,7 +200,8 @@ shellcheck: FORCE
cwltool-in-docker.sh

pyupgrade: $(PYSOURCES)
pyupgrade --exit-zero-even-if-changed --py36-plus $^
pyupgrade --exit-zero-even-if-changed --py38-plus $^
auto-walrus $^

release-test: check-python3 FORCE
git diff-index --quiet HEAD -- || ( echo You have uncommitted changes, please commit them and try again; false )
Expand Down
9 changes: 5 additions & 4 deletions cwltool/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Dict,
Iterator,
List,
Literal,
MutableMapping,
MutableSequence,
Optional,
Expand All @@ -16,7 +17,6 @@
from schema_salad.exceptions import ValidationException
from schema_salad.sourceline import SourceLine, bullets, strip_dup_lineno
from schema_salad.utils import json_dumps
from typing_extensions import Literal

from .errors import WorkflowException
from .loghandler import _logger
Expand Down Expand Up @@ -288,7 +288,9 @@ def static_checker(
)
+ "\n"
+ SourceLine(sink, "type").makeError(
" with sink '%s' of type %s" % (shortname(sink["id"]), json_dumps(sink["type"]))
" with sink '{}' of type {}".format(
shortname(sink["id"]), json_dumps(sink["type"])
)
)
)
if extra_message is not None:
Expand Down Expand Up @@ -507,8 +509,7 @@ def get_step_id(field_id: str) -> str:


def is_conditional_step(param_to_step: Dict[str, CWLObjectType], parm_id: str) -> bool:
source_step = param_to_step.get(parm_id)
if source_step is not None:
if (source_step := param_to_step.get(parm_id)) is not None:
if source_step.get("when") is not None:
return True
return False
Expand Down
6 changes: 4 additions & 2 deletions cwltool/command_line_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ def _initialworkdir(self, j: JobBase, builder: Builder) -> None:
for i, t2 in enumerate(ls):
if not isinstance(t2, Mapping):
raise SourceLine(initialWorkdir, "listing", WorkflowException, debug).makeError(
"Entry at index %s of listing is not a record, was %s" % (i, type(t2))
f"Entry at index {i} of listing is not a record, was {type(t2)}"
)

if "entry" not in t2:
Expand All @@ -715,7 +715,9 @@ def _initialworkdir(self, j: JobBase, builder: Builder) -> None:

if not isinstance(t2["entry"], Mapping):
raise SourceLine(initialWorkdir, "listing", WorkflowException, debug).makeError(
"Entry at index %s of listing is not a record, was %s" % (i, type(t2["entry"]))
"Entry at index {} of listing is not a record, was {}".format(
i, type(t2["entry"])
)
)

if t2["entry"].get("class") not in ("File", "Directory"):
Expand Down
2 changes: 1 addition & 1 deletion cwltool/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
Dict,
Iterable,
List,
Literal,
Optional,
TextIO,
Tuple,
Expand All @@ -22,7 +23,6 @@
from schema_salad.avro.schema import Names
from schema_salad.ref_resolver import Loader
from schema_salad.utils import FetcherCallableType
from typing_extensions import Literal

from .mpi import MpiConfig
from .pathmapper import PathMapper
Expand Down
40 changes: 20 additions & 20 deletions cwltool/cwlprov/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
import re
import uuid
from getpass import getuser
from typing import IO, Any, Callable, Dict, List, Optional, Tuple, Union

from typing_extensions import TypedDict
from typing import IO, Any, Callable, Dict, List, Optional, Tuple, TypedDict, Union


def _whoami() -> Tuple[str, str]:
Expand Down Expand Up @@ -112,24 +110,26 @@ def _valid_orcid(orcid: Optional[str]) -> str:
"oa:motivatedBy": Dict[str, str],
},
)
Aggregate = TypedDict(
"Aggregate",
{
"uri": Optional[str],
"bundledAs": Optional[Dict[str, Any]],
"mediatype": Optional[str],
"conformsTo": Optional[Union[str, List[str]]],
"createdOn": Optional[str],
"createdBy": Optional[Dict[str, str]],
},
total=False,
)


class Aggregate(TypedDict, total=False):
"""RO Aggregate class."""

uri: Optional[str]
bundledAs: Optional[Dict[str, Any]]
mediatype: Optional[str]
conformsTo: Optional[Union[str, List[str]]]
createdOn: Optional[str]
createdBy: Optional[Dict[str, str]]


# Aggregate.bundledAs is actually type Aggregate, but cyclic definitions are not supported
AuthoredBy = TypedDict(
"AuthoredBy",
{"orcid": Optional[str], "name": Optional[str], "uri": Optional[str]},
total=False,
)
class AuthoredBy(TypedDict, total=False):
"""RO AuthoredBy class."""

orcid: Optional[str]
name: Optional[str]
uri: Optional[str]


def checksum_copy(
Expand Down
4 changes: 2 additions & 2 deletions cwltool/cwlrdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def dot_with_parameters(g: Graph, stdout: Union[TextIO, StreamWriter]) -> None:

for step, run, _ in qres:
stdout.write(
'"%s" [label="%s"]\n' % (lastpart(step), f"{lastpart(step)} ({lastpart(run)})")
'"{}" [label="{}"]\n'.format(lastpart(step), f"{lastpart(step)} ({lastpart(run)})")
)

qres = cast(
Expand Down Expand Up @@ -170,7 +170,7 @@ def dot_without_parameters(g: Graph, stdout: Union[TextIO, StreamWriter]) -> Non

if str(runtype) != "https://w3id.org/cwl/cwl#Workflow":
stdout.write(
'"%s" [label="%s"]\n' % (dotname[step], urllib.parse.urldefrag(str(step))[1])
f'"{dotname[step]}" [label="{urllib.parse.urldefrag(str(step))[1]}"]\n' # noqa: B907
)

if currentwf is not None:
Expand Down
2 changes: 1 addition & 1 deletion cwltool/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def _get_docker_machine_mounts() -> List[str]:
"-t",
"vboxsf",
],
universal_newlines=True,
text=True,
).splitlines()
]
return __docker_machine_mounts
Expand Down
4 changes: 1 addition & 3 deletions cwltool/docker_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ def check_output_and_strip(cmd: List[str]) -> Optional[str]:
:return: Stripped string output of the command, or ``None`` if error
"""
try:
result = subprocess.check_output( # nosec
cmd, stderr=subprocess.STDOUT, universal_newlines=True
)
result = subprocess.check_output(cmd, stderr=subprocess.STDOUT, text=True) # nosec
return result.strip()
except (OSError, subprocess.CalledProcessError, TypeError, AttributeError):
# OSError is raised if command doesn't exist
Expand Down
2 changes: 1 addition & 1 deletion cwltool/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ def run(
_logger.debug("%s error", container, exc_info=True)
if docker_is_req:
raise UnsupportedRequirement(
"{} is required to run this tool: {}".format(container, str(err))
f"{container} is required to run this tool: {str(err)}"
) from err
else:
raise WorkflowException(
Expand Down
4 changes: 1 addition & 3 deletions cwltool/load_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,7 @@ def resolve_and_validate_document(
loadingContext = loadingContext.copy()

if not isinstance(workflowobj, MutableMapping):
raise ValueError(
"workflowjobj must be a dict, got '{}': {}".format(type(workflowobj), workflowobj)
)
raise ValueError(f"workflowjobj must be a dict, got {type(workflowobj)!r}: {workflowobj}")

Check warning on line 382 in cwltool/load_tool.py

View check run for this annotation

Codecov / codecov/patch

cwltool/load_tool.py#L382

Added line #L382 was not covered by tests

jobobj = None
if "cwl:tool" in workflowobj:
Expand Down
4 changes: 1 addition & 3 deletions cwltool/singularity.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,7 @@ def get_version() -> Tuple[List[int], str]:
global _SINGULARITY_VERSION # pylint: disable=global-statement
global _SINGULARITY_FLAVOR # pylint: disable=global-statement
if _SINGULARITY_VERSION is None:
version_output = check_output( # nosec
["singularity", "--version"], universal_newlines=True
).strip()
version_output = check_output(["singularity", "--version"], text=True).strip() # nosec

version_match = re.match(r"(.+) version ([0-9\.]+)", version_output)
if version_match is None:
Expand Down
5 changes: 2 additions & 3 deletions cwltool/software_requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,8 @@ def build_job_script(self, builder: "Builder", command: List[str]) -> str:
resolution_config_dict=resolution_config_dict,
conf_file=self.dependency_resolvers_config_file,
)
dependencies = get_dependencies(builder)
handle_dependencies = "" # str
if dependencies:
handle_dependencies: str = ""
if dependencies := get_dependencies(builder):
handle_dependencies = "\n".join(
tool_dependency_manager.dependency_shell_commands(
dependencies, job_directory=builder.tmpdir
Expand Down
32 changes: 15 additions & 17 deletions cwltool/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Shared functions and other definitions."""
import collections
import importlib.metadata
import os
import random
import shutil
Expand All @@ -22,32 +23,29 @@
TYPE_CHECKING,
Any,
Callable,
Deque,
Dict,
Generator,
Iterable,
List,
Literal,
MutableMapping,
MutableSequence,
NamedTuple,
Optional,
Set,
Tuple,
TypedDict,
Union,
cast,
)

import requests
from cachecontrol import CacheControl
from cachecontrol.caches import FileCache
from mypy_extensions import TypedDict, mypyc_attr
from mypy_extensions import mypyc_attr
from schema_salad.exceptions import ValidationException
from schema_salad.ref_resolver import Loader
from typing_extensions import Deque, Literal

if sys.version_info >= (3, 8):
import importlib.metadata as importlib_metadata
else:
import importlib_metadata

if TYPE_CHECKING:
from .command_line_tool import CallbackJob, ExpressionJob
Expand Down Expand Up @@ -101,14 +99,15 @@
)
JSONAtomType = Union[Dict[str, Any], List[Any], str, int, float, bool, None]
JSONType = Union[Dict[str, JSONAtomType], List[JSONAtomType], str, int, float, bool, None]
WorkflowStateItem = NamedTuple(
"WorkflowStateItem",
[
("parameter", CWLObjectType),
("value", Optional[CWLOutputType]),
("success", str),
],
)


class WorkflowStateItem(NamedTuple):
"""Workflow state item."""

parameter: CWLObjectType
value: Optional[CWLOutputType]
success: str


ParametersType = List[CWLObjectType]
StepType = CWLObjectType # WorkflowStep
Expand All @@ -118,8 +117,7 @@

def versionstring() -> str:
"""Version of CWLtool used to execute the workflow."""
pkg = importlib_metadata.version("cwltool")
if pkg:
if pkg := importlib.metadata.version("cwltool"):
return f"{sys.argv[0]} {pkg}"
return "{} {}".format(sys.argv[0], "unknown version")

Expand Down
8 changes: 2 additions & 6 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import sys
from datetime import datetime
import time
import importlib.metadata

sys.path.insert(0, os.path.abspath(".."))

Expand Down Expand Up @@ -81,12 +82,7 @@
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]


if sys.version_info >= (3, 8):
import importlib.metadata as importlib_metadata
else:
import importlib_metadata
release = importlib_metadata.version("cwltool")
release = importlib.metadata.version("cwltool")
version = ".".join(release.split(".")[:2])

autoapi_dirs = ["../cwltool"]
Expand Down
7 changes: 2 additions & 5 deletions gittaggers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@
import sys
import time

if sys.version_info >= (3, 8):
import importlib.metadata as importlib_metadata
else:
import importlib_metadata
import importlib.metadata

from typing import Any

from setuptools.command.egg_info import egg_info

SETUPTOOLS_VER = importlib_metadata.version("setuptools").split(".")
SETUPTOOLS_VER = importlib.metadata.version("setuptools").split(".")

RECENT_SETUPTOOLS = (
int(SETUPTOOLS_VER[0]) > 40
Expand Down
Loading

0 comments on commit 2989ba9

Please sign in to comment.