Skip to content

Commit d26b6f7

Browse files
committed
Drop support for Python 3.8
1 parent 9146245 commit d26b6f7

35 files changed

+336
-429
lines changed

.github/workflows/ci-tests.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ jobs:
1515
tox:
1616
name: CI tests via Tox
1717

18-
runs-on: ubuntu-22.04
18+
runs-on: ubuntu-24.04
1919

2020
strategy:
2121
matrix:
2222
py-ver-major: [3]
23-
py-ver-minor: [8, 9, 10, 11, 12, 13]
23+
py-ver-minor: [9, 10, 11, 12, 13]
2424
step: [lint, unit, bandit, mypy]
2525

2626
env:
@@ -35,8 +35,8 @@ jobs:
3535
- name: Set up Singularity
3636
if: ${{ matrix.step == 'unit' || matrix.step == 'mypy' }}
3737
run: |
38-
wget --no-verbose https://github.com/sylabs/singularity/releases/download/v3.11.4/singularity-ce_3.11.4-jammy_amd64.deb
39-
sudo apt-get install -y ./singularity-ce_3.11.4-jammy_amd64.deb
38+
wget --no-verbose https://github.com/sylabs/singularity/releases/download/v4.2.1/singularity-ce_4.2.1-noble_amd64.deb
39+
sudo apt-get install -y ./singularity-ce_4.2.1-noble_amd64.deb
4040
4141
- name: Set up Python
4242
uses: actions/setup-python@v5
@@ -74,7 +74,7 @@ jobs:
7474
tox-style:
7575
name: CI linters via Tox
7676

77-
runs-on: ubuntu-22.04
77+
runs-on: ubuntu-24.04
7878

7979
strategy:
8080
matrix:
@@ -109,7 +109,7 @@ jobs:
109109

110110
release_test:
111111
name: cwl-utils release test
112-
runs-on: ubuntu-22.04
112+
runs-on: ubuntu-24.04
113113

114114
steps:
115115
- uses: actions/checkout@v4

.github/workflows/tag_to_publish.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,20 @@ jobs:
1212
release_to_pypi:
1313
name: cwl-utils release test
1414

15-
runs-on: ubuntu-22.04
15+
runs-on: ubuntu-24.04
1616

1717
steps:
1818
- uses: actions/checkout@v4
1919

2020
- name: Set up Singularity
2121
run: |
22-
wget --no-verbose https://github.com/sylabs/singularity/releases/download/v3.11.4/singularity-ce_3.11.4-jammy_amd64.deb
23-
sudo apt-get install -y ./singularity-ce_3.11.4-jammy_amd64.deb
22+
wget --no-verbose https://github.com/sylabs/singularity/releases/download/v4.2.1/singularity-ce_4.2.1-noble_amd64.deb
23+
sudo apt-get install -y ./singularity-ce_4.2.1-noble_amd64.deb
2424
2525
- name: Set up Python
2626
uses: actions/setup-python@v5
2727
with:
28-
python-version: 3.11
28+
python-version: 3.12
2929

3030
- name: Cache for pip
3131
uses: actions/cache@v4

CONTRIBUTING.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Style guide:
22
- PEP-8 / format with ``black`` via ``make format``
3-
- Python 3.8+ compatible code
3+
- Python 3.9+ compatible code
44
- PEP-484 type hints
55

66
It is suggested that you run `git config blame.ignoreRevsFile .git-blame-ignore-revs`
@@ -17,7 +17,7 @@ Here's a rough guide (improvements are welcome!)
1717
- Install cwl-utils in the virtual environment: ``pip install -e .``
1818
- Check the version which might be different from the version installed in general on any system: ``pip show cwl-utils``
1919
- After you've made the changes, you can the complete test suite via tox: ``tox``
20-
- If you want to run specific tests, say ``unit tests`` in Python 3.8, then: ``tox -e py38-unit``.
21-
- Look at ``tox.ini`` for all available tests and runtimes
20+
- If you want to run specific tests, say ``unit tests`` in Python 3.13, then: ``tox -e py313-unit``.
21+
- Look at ``tox -l`` for all available tests and runtimes
2222
- If tests are passing, you can create a PR on ``cwl-utils`` GitHub repository.
2323
- After you're done working on the ``cwl-utils``, you can deactivate the virtual environment: ``deactivate``

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ shellcheck: FORCE
177177
shellcheck release-test.sh
178178

179179
pyupgrade: $(PYSOURCES)
180-
pyupgrade --exit-zero-even-if-changed --py38-plus $^
180+
pyupgrade --exit-zero-even-if-changed --py39-plus $^
181181
auto-walrus $^
182182

183183
release-test: FORCE

cwl_utils/__meta__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# SPDX-License-Identifier: Apache-2.0
22
"""Global version number for the cwl_utils package."""
3-
__version__ = "0.35"
3+
__version__ = "0.36"

cwl_utils/cite_extract.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
# SPDX-License-Identifier: Apache-2.0
33
import argparse
44
import sys
5-
from typing import Iterator, cast
5+
from collections.abc import Iterator
6+
from typing import cast
67

78
import cwl_utils.parser as cwl
89

cwl_utils/cwl_v1_0_expression_refactor.py

Lines changed: 44 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,8 @@
44
"""CWL Expression refactoring tool for CWL v1.0 ."""
55
import copy
66
import hashlib
7-
from collections.abc import Mapping
8-
from typing import (
9-
Any,
10-
Dict,
11-
List,
12-
MutableSequence,
13-
Optional,
14-
Sequence,
15-
Tuple,
16-
Type,
17-
Union,
18-
cast,
19-
)
7+
from collections.abc import Mapping, MutableSequence, Sequence
8+
from typing import Any, Optional, Union, cast
209

2110
from ruamel import yaml
2211
from schema_salad.sourceline import SourceLine
@@ -142,7 +131,7 @@ def get_expression(
142131

143132

144133
def etool_to_cltool(
145-
etool: cwl.ExpressionTool, expressionLib: Optional[List[str]] = None
134+
etool: cwl.ExpressionTool, expressionLib: Optional[list[str]] = None
146135
) -> cwl.CommandLineTool:
147136
"""Convert a ExpressionTool to a CommandLineTool."""
148137
inputs = yaml.comments.CommentedSeq() # preserve the order
@@ -216,7 +205,7 @@ def traverse(
216205
inside: bool,
217206
skip_command_line1: bool,
218207
skip_command_line2: bool,
219-
) -> Tuple[Union[cwl.CommandLineTool, cwl.ExpressionTool, cwl.Workflow], bool]:
208+
) -> tuple[Union[cwl.CommandLineTool, cwl.ExpressionTool, cwl.Workflow], bool]:
220209
"""Convert the given process and any subprocesses."""
221210
if not inside and isinstance(process, cwl.CommandLineTool):
222211
process = expand_stream_shortcuts(process)
@@ -330,7 +319,7 @@ def generate_etool_from_expr(
330319
Union[
331320
cwl.InputParameter,
332321
cwl.CommandInputParameter,
333-
List[Union[cwl.InputParameter, cwl.CommandInputParameter]],
322+
list[Union[cwl.InputParameter, cwl.CommandInputParameter]],
334323
]
335324
] = None, # if the "self" input should be a different type than the "result" output
336325
extra_processes: Optional[
@@ -344,7 +333,7 @@ def generate_etool_from_expr(
344333
self_type = target
345334
if isinstance(self_type, list):
346335
new_type: Union[
347-
List[Union[cwl.ArraySchema, cwl.InputRecordSchema]],
336+
list[Union[cwl.ArraySchema, cwl.InputRecordSchema]],
348337
Union[cwl.ArraySchema, cwl.InputRecordSchema],
349338
] = [clean_type_ids(t.type_) for t in self_type if t.type_]
350339
elif self_type.type_:
@@ -420,7 +409,7 @@ def get_input_for_id(
420409
"""Determine the CommandInputParameter for the given input name."""
421410
name = name.split("/")[-1]
422411

423-
for inp in cast(List[cwl.CommandInputParameter], tool.inputs):
412+
for inp in cast(list[cwl.CommandInputParameter], tool.inputs):
424413
if inp.id and inp.id.split("#")[-1].split("/")[-1] == name:
425414
return inp
426415
if isinstance(tool, cwl.Workflow) and "/" in name:
@@ -437,7 +426,7 @@ def find_expressionLib(
437426
processes: Sequence[
438427
Union[cwl.CommandLineTool, cwl.Workflow, cwl.ExpressionTool, cwl.WorkflowStep]
439428
]
440-
) -> Optional[List[str]]:
429+
) -> Optional[list[str]]:
441430
"""
442431
Return the expressionLib from the highest priority InlineJavascriptRequirement.
443432
@@ -448,7 +437,7 @@ def find_expressionLib(
448437
if process.requirements:
449438
for req in process.requirements:
450439
if isinstance(req, cwl.InlineJavascriptRequirement):
451-
return cast(Optional[List[str]], copy.deepcopy(req.expressionLib))
440+
return cast(Optional[list[str]], copy.deepcopy(req.expressionLib))
452441
return None
453442

454443

@@ -457,15 +446,15 @@ def replace_expr_with_etool(
457446
name: str,
458447
workflow: cwl.Workflow,
459448
target: Union[cwl.CommandInputParameter, cwl.InputParameter],
460-
source: Optional[Union[str, List[Any]]],
449+
source: Optional[Union[str, list[Any]]],
461450
replace_etool: bool = False,
462451
extra_process: Optional[
463452
Union[cwl.Workflow, cwl.WorkflowStep, cwl.CommandLineTool]
464453
] = None,
465454
source_type: Optional[cwl.CommandInputParameter] = None,
466455
) -> None:
467456
"""Modify the given workflow, replacing the expr with an standalone ExpressionTool."""
468-
extra_processes: List[
457+
extra_processes: list[
469458
Union[cwl.Workflow, cwl.WorkflowStep, cwl.CommandLineTool]
470459
] = [workflow]
471460
if extra_process:
@@ -474,7 +463,7 @@ def replace_expr_with_etool(
474463
expr, target, source is None, source_type, extra_processes
475464
)
476465
if replace_etool:
477-
processes: List[Union[cwl.WorkflowStep, cwl.Workflow, cwl.CommandLineTool]] = [
466+
processes: list[Union[cwl.WorkflowStep, cwl.Workflow, cwl.CommandLineTool]] = [
478467
workflow
479468
]
480469
if extra_process:
@@ -528,7 +517,7 @@ def empty_inputs(
528517
cwl.CommandLineTool, cwl.WorkflowStep, cwl.ExpressionTool, cwl.Workflow
529518
],
530519
parent: Optional[cwl.Workflow] = None,
531-
) -> Dict[str, Any]:
520+
) -> dict[str, Any]:
532521
"""Produce a mock input object for the given inputs."""
533522
result = {}
534523
if isinstance(process_or_step, cwl.Process):
@@ -662,22 +651,22 @@ def process_workflow_reqs_and_hints(
662651
# and connecting all workflow inputs to the generated step
663652
modified = False
664653
inputs = empty_inputs(workflow)
665-
generated_res_reqs: List[Tuple[str, Union[int, str]]] = []
666-
generated_iwdr_reqs: List[Tuple[str, Union[int, str]]] = []
667-
generated_envVar_reqs: List[Tuple[str, Union[int, str]]] = []
668-
prop_reqs: Tuple[
654+
generated_res_reqs: list[tuple[str, Union[int, str]]] = []
655+
generated_iwdr_reqs: list[tuple[str, Union[int, str]]] = []
656+
generated_envVar_reqs: list[tuple[str, Union[int, str]]] = []
657+
prop_reqs: tuple[
669658
Union[
670-
Type[cwl.EnvVarRequirement],
671-
Type[cwl.ResourceRequirement],
672-
Type[cwl.InitialWorkDirRequirement],
659+
type[cwl.EnvVarRequirement],
660+
type[cwl.ResourceRequirement],
661+
type[cwl.InitialWorkDirRequirement],
673662
],
674663
...,
675664
] = ()
676665
resourceReq: Optional[cwl.ResourceRequirement] = None
677666
envVarReq: Optional[cwl.EnvVarRequirement] = None
678667
iwdr: Optional[cwl.InitialWorkDirRequirement] = None
679668
if workflow.requirements is not None:
680-
for req in cast(List[cwl.ProcessRequirement], workflow.requirements):
669+
for req in cast(list[cwl.ProcessRequirement], workflow.requirements):
681670
if req and isinstance(req, cwl.EnvVarRequirement):
682671
if req.envDef:
683672
for index, envDef in enumerate(req.envDef):
@@ -994,9 +983,9 @@ def process_level_reqs(
994983
modified = False
995984
target_process = step.run
996985
inputs = empty_inputs(process)
997-
generated_res_reqs: List[Tuple[str, str]] = []
998-
generated_iwdr_reqs: List[Tuple[str, Union[int, str], Any]] = []
999-
generated_envVar_reqs: List[Tuple[str, Union[int, str]]] = []
986+
generated_res_reqs: list[tuple[str, str]] = []
987+
generated_iwdr_reqs: list[tuple[str, Union[int, str], Any]] = []
988+
generated_envVar_reqs: list[tuple[str, Union[int, str]]] = []
1000989
if not step.id:
1001990
return False
1002991
step_name = step.id.split("#", 1)[-1]
@@ -1378,7 +1367,7 @@ def traverse_CommandLineTool(
13781367
}
13791368
]
13801369
if outp.outputBinding.loadContents:
1381-
cast(Dict[Any, Any], self)[0]["contents"] = "stuff"
1370+
cast(dict[Any, Any], self)[0]["contents"] = "stuff"
13821371
expression = get_expression(outp.outputBinding.outputEval, inputs, self)
13831372
if expression:
13841373
modified = True
@@ -1635,7 +1624,7 @@ def replace_clt_hintreq_expr_with_etool(
16351624

16361625
def cltool_inputs_to_etool_inputs(
16371626
tool: cwl.CommandLineTool,
1638-
) -> List[cwl.InputParameter]:
1627+
) -> list[cwl.InputParameter]:
16391628
"""Copy CommandLineTool input objects into the equivalent ExpressionTool input objects."""
16401629
inputs = yaml.comments.CommentedSeq()
16411630
if tool.inputs:
@@ -1661,7 +1650,7 @@ def cltool_inputs_to_etool_inputs(
16611650

16621651
def cltool_step_outputs_to_workflow_outputs(
16631652
cltool_step: cwl.WorkflowStep, etool_step_id: str, etool_out_id: str
1664-
) -> List[cwl.OutputParameter]:
1653+
) -> list[cwl.OutputParameter]:
16651654
"""
16661655
Copy CommandLineTool outputs into the equivalent Workflow output parameters.
16671656
@@ -1731,7 +1720,7 @@ def generate_etool_from_expr2(
17311720
}"""
17321721
)
17331722
hints = None
1734-
procs: List[
1723+
procs: list[
17351724
Union[cwl.CommandLineTool, cwl.ExpressionTool, cwl.Workflow, cwl.WorkflowStep]
17361725
] = []
17371726
if process:
@@ -1820,12 +1809,12 @@ def traverse_step(
18201809
raise WorkflowException("target not found")
18211810
input_source_id = None
18221811
source_type: Optional[
1823-
Union[List[cwl.InputParameter], cwl.InputParameter]
1812+
Union[list[cwl.InputParameter], cwl.InputParameter]
18241813
] = None
18251814
if inp.source:
18261815
if isinstance(inp.source, MutableSequence):
18271816
input_source_id = []
1828-
source_types: List[cwl.InputParameter] = []
1817+
source_types: list[cwl.InputParameter] = []
18291818
for source in inp.source:
18301819
source_id = source.split("#")[-1]
18311820
input_source_id.append(source_id)
@@ -1851,7 +1840,7 @@ def traverse_step(
18511840
# target.id = target.id.split('#')[-1]
18521841
if isinstance(original_process, cwl.ExpressionTool):
18531842
found_JSReq = False
1854-
reqs: List[cwl.ProcessRequirement] = []
1843+
reqs: list[cwl.ProcessRequirement] = []
18551844
if original_process.hints:
18561845
reqs.extend(original_process.hints)
18571846
if original_process.requirements:
@@ -1907,8 +1896,8 @@ def traverse_step(
19071896

19081897

19091898
def workflow_step_to_InputParameters(
1910-
step_ins: List[cwl.WorkflowStepInput], parent: cwl.Workflow, except_in_id: str
1911-
) -> List[cwl.InputParameter]:
1899+
step_ins: list[cwl.WorkflowStepInput], parent: cwl.Workflow, except_in_id: str
1900+
) -> list[cwl.InputParameter]:
19121901
"""Create InputParameters to match the given WorkflowStep inputs."""
19131902
params = []
19141903
for inp in step_ins:
@@ -1947,10 +1936,10 @@ def replace_step_valueFrom_expr_with_etool(
19471936
step: cwl.WorkflowStep,
19481937
step_inp: cwl.WorkflowStepInput,
19491938
original_process: Union[cwl.CommandLineTool, cwl.ExpressionTool],
1950-
original_step_ins: List[cwl.WorkflowStepInput],
1951-
source: Optional[Union[str, List[str]]],
1939+
original_step_ins: list[cwl.WorkflowStepInput],
1940+
source: Optional[Union[str, list[str]]],
19521941
replace_etool: bool,
1953-
source_type: Optional[Union[cwl.InputParameter, List[cwl.InputParameter]]] = None,
1942+
source_type: Optional[Union[cwl.InputParameter, list[cwl.InputParameter]]] = None,
19541943
) -> None:
19551944
"""Replace a WorkflowStep level 'valueFrom' expression with a sibling ExpressionTool step."""
19561945
if not step_inp.id:
@@ -1972,12 +1961,16 @@ def replace_step_valueFrom_expr_with_etool(
19721961
[workflow, step],
19731962
)
19741963
if replace_etool:
1975-
processes = [
1964+
processes: list[
1965+
Union[
1966+
cwl.Workflow, cwl.CommandLineTool, cwl.ExpressionTool, cwl.WorkflowStep
1967+
]
1968+
] = [
19761969
workflow,
19771970
step,
1978-
] # type: List[Union[cwl.Workflow, cwl.CommandLineTool, cwl.ExpressionTool, cwl.WorkflowStep]]
1971+
]
19791972
cltool = etool_to_cltool(temp_etool, find_expressionLib(processes))
1980-
etool = cltool # type: Union[cwl.ExpressionTool, cwl.CommandLineTool]
1973+
etool: Union[cwl.ExpressionTool, cwl.CommandLineTool] = cltool
19811974
else:
19821975
etool = temp_etool
19831976
wf_step_inputs = copy.deepcopy(original_step_ins)
@@ -2026,7 +2019,7 @@ def traverse_workflow(
20262019
replace_etool: bool,
20272020
skip_command_line1: bool,
20282021
skip_command_line2: bool,
2029-
) -> Tuple[cwl.Workflow, bool]:
2022+
) -> tuple[cwl.Workflow, bool]:
20302023
"""Traverse a workflow, processing each step."""
20312024
modified = False
20322025
for index, step in enumerate(workflow.steps):

0 commit comments

Comments
 (0)