Skip to content

Commit 767ea45

Browse files
committed
Drop support for Python 3.8
1 parent 39c4143 commit 767ea45

14 files changed

+115
-115
lines changed

.github/workflows/ci-tests.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ jobs:
3030
name: Tox
3131
runs-on: ubuntu-22.04
3232
strategy:
33+
fail-fast: false
3334
matrix:
3435
py-ver-major: [3]
35-
py-ver-minor: [8, 9, 10, 11, 12]
36+
py-ver-minor: [9, 10, 11, 12]
3637
step: [lint, unit, bandit, mypy]
3738

3839
env:

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ shellcheck: FORCE
171171
shellcheck release-test.sh
172172

173173
pyupgrade: $(PYSOURCES)
174-
pyupgrade --exit-zero-even-if-changed --py38-plus $^
174+
pyupgrade --exit-zero-even-if-changed --py39-plus $^
175175
auto-walrus $^
176176

177177
release-test: FORCE

cwl_flask.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
import tempfile
99
import threading
1010
import time
11-
from typing import Any, Dict, Generator, List, Tuple
11+
from collections.abc import Generator
12+
from typing import Any
1213

1314
import werkzeug.wrappers.response
1415
import yaml
@@ -17,7 +18,7 @@
1718
app = Flask(__name__)
1819

1920
jobs_lock = threading.Lock()
20-
jobs: List["Job"] = []
21+
jobs: list["Job"] = []
2122

2223

2324
class Job(threading.Thread):
@@ -66,7 +67,7 @@ def run(self) -> None:
6667
with self.updatelock:
6768
self.status["state"] = "Failed"
6869

69-
def getstatus(self) -> Dict[str, Any]:
70+
def getstatus(self) -> dict[str, Any]:
7071
"""Report the current status."""
7172
with self.updatelock:
7273
return self.status.copy()
@@ -106,7 +107,7 @@ def runworkflow() -> werkzeug.wrappers.response.Response:
106107

107108

108109
@app.route("/jobs/<int:jobid>", methods=["GET", "POST"])
109-
def jobcontrol(jobid: int) -> Tuple[str, int]:
110+
def jobcontrol(jobid: int) -> tuple[str, int]:
110111
"""Accept a job related action and report the result."""
111112
with jobs_lock:
112113
job = jobs[jobid]
@@ -152,7 +153,7 @@ def getjobs() -> Response:
152153
with jobs_lock:
153154
jobscopy = copy.copy(jobs)
154155

155-
def spool(jc: List[Job]) -> Generator[str, None, None]:
156+
def spool(jc: list[Job]) -> Generator[str, None, None]:
156157
yield "["
157158
first = True
158159
for j in jc:

cwltool_stream.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
import sys
66
import tempfile
77
from io import StringIO
8-
from typing import List, Union
8+
from typing import Union
99

1010
import cwltool.main
1111

1212
_logger = logging.getLogger("cwltool")
1313
_logger.setLevel(logging.ERROR)
1414

1515

16-
def main(args: List[str] = sys.argv[1:]) -> int:
16+
def main(args: list[str] = sys.argv[1:]) -> int:
1717
"""Streaming execution of cwltool."""
1818
if len(args) == 0:
1919
print("Workflow must be on command line")

pyproject.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ classifiers = [
1515
"Operating System :: MacOS :: MacOS X",
1616
"Operating System :: POSIX",
1717
"Programming Language :: Python",
18-
"programming language :: python :: 3.7",
19-
"Programming Language :: Python :: 3.8",
2018
"Programming Language :: Python :: 3.9",
2119
"Programming Language :: Python :: 3.10",
20+
"Programming Language :: Python :: 3.11",
21+
"Programming Language :: Python :: 3.12",
2222
"Topic :: Software Development :: Libraries :: Python Modules",
2323
]
24-
requires-python = "~=3.7"
24+
requires-python = ">=3.9"
2525
dependencies = [
2626
"connexion[swagger-ui] >= 2.0.2, < 3",
2727
"ruamel.yaml >= 0.15.78",

test/test_integration.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import subprocess
66
import time
77
import unittest
8-
from typing import List, Optional, Tuple, cast
8+
from typing import Optional, cast
99

1010
import pytest
1111
import requests
@@ -21,10 +21,10 @@ class IntegrationTest(unittest.TestCase):
2121
cwl_dockstore_url: str
2222
cwl_local_path: str
2323
cwl_json_input: str
24-
cwl_attachments: List[str]
24+
cwl_attachments: list[str]
2525
wdl_local_path: str
2626
wdl_json_input: str
27-
wdl_attachments: List[str]
27+
wdl_attachments: list[str]
2828
client: WESClient
2929
manual: bool
3030
wes_server_process: "subprocess.Popen[bytes]"
@@ -168,8 +168,8 @@ def run_md5sum(
168168
self,
169169
wf_input: str,
170170
json_input: str,
171-
workflow_attachment: Optional[List[str]] = None,
172-
) -> Tuple[str, str]:
171+
workflow_attachment: Optional[list[str]] = None,
172+
) -> tuple[str, str]:
173173
"""
174174
Pass a local md5sum cwl to the wes-service server.
175175
@@ -216,7 +216,7 @@ def check_for_file(self, filepath: str, seconds: int = 120) -> bool:
216216
return True
217217

218218

219-
def get_server_pids() -> Optional[List[bytes]]:
219+
def get_server_pids() -> Optional[list[bytes]]:
220220
try:
221221
pids = (
222222
subprocess.check_output(["pgrep", "-f", "wes_service_main.py"])

tox.ini

+26-27
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,62 @@
11
[tox]
22
envlist =
3-
py3{8,9,10,11,12}-lint,
4-
py3{8,9,10,11,12}-unit,
5-
py3{8,9,10,11,12}-bandit,
6-
py3{8,9,10,11,12}-mypy,
3+
py3{9,10,11,12}-lint,
4+
py3{9,10,11,12}-unit,
5+
py3{9,10,11,12}-bandit,
6+
py3{9,10,11,12}-mypy,
77
py312-lintreadme,
88
py312-pydocstyle
99
isolated_build = True
1010
skip_missing_interpreters = True
1111

1212
[gh-actions]
1313
python =
14-
3.8: py38
1514
3.9: py39
1615
3.10: py310
1716
3.11: py311
1817
3.12: py312
1918

2019
[testenv]
2120
description =
22-
py3{8,9,10,11,12}-unit: Run the unit tests
23-
py3{8,9,10,11,12}-lint: Lint the Python code
24-
py3{8,9,10,11,12}-bandit: Search for common security issues
25-
py3{8,9,10,11,12}-mypy: Check for type safety
21+
py3{9,10,11,12}-unit: Run the unit tests
22+
py3{9,10,11,12}-lint: Lint the Python code
23+
py3{9,10,11,12}-bandit: Search for common security issues
24+
py3{9,10,11,12}-mypy: Check for type safety
2625
py312-pydocstyle: docstring style checker
2726
py312-lintreadme: Lint the README.rst->.md conversion
2827

2928
passenv =
3029
CI
3130
GITHUB_*
3231
deps =
33-
py3{8,9,10,11,12}-mypy: -rmypy-requirements.txt
34-
py3{8,9,10,11,12}-{unit,mypy}: -rrequirements.txt
35-
py3{8,9,10,11,12}-{unit,mypy}: -rtest-requirements.txt
36-
py3{8,9,10,11,12}-lint: -rlint-requirements.txt
37-
py3{8,9,10,11,12}-bandit: bandit
32+
py3{9,10,11,12}-mypy: -rmypy-requirements.txt
33+
py3{9,10,11,12}-{unit,mypy}: -rrequirements.txt
34+
py3{9,10,11,12}-{unit,mypy}: -rtest-requirements.txt
35+
py3{9,10,11,12}-lint: -rlint-requirements.txt
36+
py3{9,10,11,12}-bandit: bandit
3837

3938
setenv =
40-
py3{8,9,10,11,12}-unit: LC_ALL = C.UTF-8
39+
py3{9,10,11,12}-unit: LC_ALL = C.UTF-8
4140

4241
commands =
43-
py3{8,9,10,11,12}-unit: python -m pip install -U pip setuptools wheel
44-
py3{8,9,10,11,12}-unit: make coverage-report coverage.xml PYTEST_EXTRA={posargs}
45-
py3{8,9,10,11,12}-bandit: bandit --recursive wes_client wes_service
46-
py3{8,9,10,11,12}-lint: make flake8
47-
py3{8,9,10,11,12}-lint: make format-check
48-
py3{8,9,10,11,12}-mypy: make mypy
42+
py3{9,10,11,12}-unit: python -m pip install -U pip setuptools wheel
43+
py3{9,10,11,12}-unit: make coverage-report coverage.xml PYTEST_EXTRA={posargs}
44+
py3{9,10,11,12}-bandit: bandit --recursive wes_client wes_service
45+
py3{9,10,11,12}-lint: make flake8
46+
py3{9,10,11,12}-lint: make format-check
47+
py3{9,10,11,12}-mypy: make mypy
4948

5049
allowlist_externals =
51-
py3{8,9,10,11,12}-lint: flake8
52-
py3{8,9,10,11,12}-lint: black
53-
py3{8,9,10,11,12}-{mypy,memleak,shellcheck,lint,lintreadme,unit}: make
50+
py3{9,10,11,12}-lint: flake8
51+
py3{9,10,11,12}-lint: black
52+
py3{9,10,11,12}-{mypy,memleak,shellcheck,lint,lintreadme,unit}: make
5453

5554
skip_install =
56-
py3{8,9,10,11,12}-lint: true
57-
py3{8,9,10,11,12}-bandit: true
55+
py3{9,10,11,12}-lint: true
56+
py3{9,10,11,12}-bandit: true
5857

5958
extras =
60-
py3{8,9,10,11,12}-unit: toil
59+
py3{9,10,11,12}-unit: toil
6160

6261
[testenv:py312-pydocstyle]
6362
allowlist_externals = make

wes_client/util.py

+16-16
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import os
77
import sys
88
from subprocess import DEVNULL, CalledProcessError, check_call # nosec B404
9-
from typing import Any, Dict, List, Optional, Set, Tuple, Union, cast
9+
from typing import Any, Optional, Union, cast
1010
from urllib.request import pathname2url, urlopen
1111

1212
import requests
@@ -51,7 +51,7 @@ def get_version(extension: str, workflow_file: str) -> str:
5151
return "draft-2"
5252

5353

54-
def wf_info(workflow_path: str) -> Tuple[str, str]:
54+
def wf_info(workflow_path: str) -> tuple[str, str]:
5555
"""
5656
Return the version of the file and the file extension.
5757
@@ -127,8 +127,8 @@ def fixpaths(d: Any) -> None:
127127

128128

129129
def build_wes_request(
130-
workflow_file: str, json_path: str, attachments: Optional[List[str]] = None
131-
) -> List[Tuple[str, Any]]:
130+
workflow_file: str, json_path: str, attachments: Optional[list[str]] = None
131+
) -> list[tuple[str, Any]]:
132132
"""
133133
:param workflow_file: Path to cwl/wdl file. Can be http/https/file.
134134
:param json_path: Path to accompanying json file.
@@ -151,7 +151,7 @@ def build_wes_request(
151151
wf_params = json_path
152152
wf_version, wf_type = wf_info(workflow_file)
153153

154-
parts: List[Tuple[str, Any]] = [
154+
parts: list[tuple[str, Any]] = [
155155
("workflow_params", wf_params),
156156
("workflow_type", wf_type),
157157
("workflow_type_version", wf_version),
@@ -187,7 +187,7 @@ def build_wes_request(
187187
return parts
188188

189189

190-
def expand_globs(attachments: Optional[Union[List[str], str]]) -> Set[str]:
190+
def expand_globs(attachments: Optional[Union[list[str], str]]) -> set[str]:
191191
"""Expand any globs present in the attachment list."""
192192
expanded_list = []
193193
if attachments is None:
@@ -204,26 +204,26 @@ def expand_globs(attachments: Optional[Union[List[str], str]]) -> Set[str]:
204204
return set(expanded_list)
205205

206206

207-
def wes_response(postresult: requests.Response) -> Dict[str, Any]:
207+
def wes_response(postresult: requests.Response) -> dict[str, Any]:
208208
"""Convert a Response object to JSON text."""
209209
if postresult.status_code != 200:
210210
error = str(json.loads(postresult.text))
211211
logging.error(error)
212212
raise Exception(error)
213213

214-
return cast(Dict[str, Any], json.loads(postresult.text))
214+
return cast(dict[str, Any], json.loads(postresult.text))
215215

216216

217217
class WESClient:
218218
"""WES client."""
219219

220-
def __init__(self, service: Dict[str, Any]):
220+
def __init__(self, service: dict[str, Any]):
221221
"""Initialize the cliet with the provided credentials and endpoint."""
222222
self.auth = service["auth"]
223223
self.proto = service["proto"]
224224
self.host = service["host"]
225225

226-
def get_service_info(self) -> Dict[str, Any]:
226+
def get_service_info(self) -> dict[str, Any]:
227227
"""
228228
Get information about Workflow Execution Service. May
229229
include information related (but not limited to) the
@@ -242,7 +242,7 @@ def get_service_info(self) -> Dict[str, Any]:
242242
)
243243
return wes_response(postresult)
244244

245-
def list_runs(self) -> Dict[str, Any]:
245+
def list_runs(self) -> dict[str, Any]:
246246
"""
247247
List the workflows, this endpoint will list the workflows
248248
in order of oldest to newest. There is no guarantee of
@@ -260,8 +260,8 @@ def list_runs(self) -> Dict[str, Any]:
260260
return wes_response(postresult)
261261

262262
def run(
263-
self, wf: str, jsonyaml: str, attachments: Optional[List[str]]
264-
) -> Dict[str, Any]:
263+
self, wf: str, jsonyaml: str, attachments: Optional[list[str]]
264+
) -> dict[str, Any]:
265265
"""
266266
Composes and sends a post request that signals the wes server to run a workflow.
267267
@@ -283,7 +283,7 @@ def run(
283283
)
284284
return wes_response(postresult)
285285

286-
def cancel(self, run_id: str) -> Dict[str, Any]:
286+
def cancel(self, run_id: str) -> dict[str, Any]:
287287
"""
288288
Cancel a running workflow.
289289
@@ -299,7 +299,7 @@ def cancel(self, run_id: str) -> Dict[str, Any]:
299299
)
300300
return wes_response(postresult)
301301

302-
def get_run_log(self, run_id: str) -> Dict[str, Any]:
302+
def get_run_log(self, run_id: str) -> dict[str, Any]:
303303
"""
304304
Get detailed info about a running workflow.
305305
@@ -315,7 +315,7 @@ def get_run_log(self, run_id: str) -> Dict[str, Any]:
315315
)
316316
return wes_response(postresult)
317317

318-
def get_run_status(self, run_id: str) -> Dict[str, Any]:
318+
def get_run_status(self, run_id: str) -> dict[str, Any]:
319319
"""
320320
Get quick status info about a running workflow.
321321

wes_client/wes_client_main.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@
66
import sys
77
import time
88
from importlib.metadata import version
9-
from typing import List
109

1110
import requests
1211
from requests.exceptions import InvalidSchema, MissingSchema
1312

1413
from wes_client.util import WESClient, modify_jsonyaml_paths
1514

1615

17-
def main(argv: List[str] = sys.argv[1:]) -> int:
16+
def main(argv: list[str] = sys.argv[1:]) -> int:
1817
"""Run the WES service."""
1918
parser = argparse.ArgumentParser(description="Workflow Execution Service")
2019
parser.add_argument(

0 commit comments

Comments
 (0)