Skip to content

Commit 6ab6fd1

Browse files
authored
Merge pull request #125 from inab/full_circle
Release 1.0.0rc1
2 parents 1564bc3 + c869d35 commit 6ab6fd1

File tree

16 files changed

+455
-89
lines changed

16 files changed

+455
-89
lines changed

.github/workflows/pre-commit.yml

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
runs-on: ubuntu-latest
1313
strategy:
1414
matrix:
15-
python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11", "3.12" ]
15+
python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13" ]
1616
name: Pre-commit python ${{ matrix.python-version }}
1717
steps:
1818
- uses: actions/checkout@v4
@@ -33,16 +33,15 @@ jobs:
3333
with:
3434
files: requirements.txt
3535

36-
- name: 'Install requirements (standard)'
37-
if: ${{ matrix.python-version != '3.6' && steps.changed-requirements-txt.outputs.any_changed == 'true' }}
36+
- name: 'Install requirements (standard or constraints ${{ matrix.python-version }})'
37+
if: ${{ matrix.python-version != '3.6' }}
3838
run: |
3939
pip install --upgrade pip wheel
40-
pip install -r requirements.txt
41-
- name: 'Install requirements (constraints)'
42-
if: ${{ matrix.python-version != '3.6' && steps.changed-requirements-txt.outputs.any_changed != 'true' }}
43-
run: |
44-
pip install --upgrade pip wheel
45-
pip install -r requirements.txt -c constraints-${{ matrix.python-version }}.txt
40+
if [ ${{ steps.changed-requirements-txt.outputs.any_changed }} != 'true' ] && [ -f constraints-${{ matrix.python-version }}.txt ] ; then
41+
pip install -r requirements.txt -c constraints-${{ matrix.python-version }}.txt
42+
else
43+
pip install -r requirements.txt
44+
fi
4645
#- name: 'Install requirements (custom Python ${{ matrix.python-version }})'
4746
# if: ${{ matrix.python-version == '3.6' }}
4847
# run: |

CITATION.cff

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ keywords:
2525
license: Apache-2.0
2626
message: "If you use this software, please cite it using these metadata."
2727
repository-code: "https://github.com/inab/WfExS-backend"
28+
repository-artifact: "https://github.com/inab/WfExS-backend/pkgs/container/wfexs-backend"
2829
type: software
2930
title: "WfExS-backend"
30-
version: 1.0.0rc0
31-
date-released: "2024-08-07"
31+
version: 1.0.0rc1
32+
date-released: "2024-10-16"

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ Visit the [Zenodo record](https://doi.org/10.5281/zenodo.6567591) for the latest
4040

4141
### Presentations and outreach
4242

43+
Additional present and future list of references is hosted at [WfExS-backend ReadTheDocs outreach](https://wfexs-backend.readthedocs.io/en/latest/outreach.html).
44+
4345
Paula Iborra, José M. Fernández, Salvador Capella-Gutierrez (2024):
4446
[**Onboarding Snakemake: Progress towards WfExS-backend integration**](https://doi.org/10.7490/f1000research.1119725.1).
4547
_F1000Research_ **13**(ELIXIR):551 (poster)

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@
8282
"Programming Language :: Python :: 3.10",
8383
"Programming Language :: Python :: 3.11",
8484
"Programming Language :: Python :: 3.12",
85-
"Development Status :: 3 - Alpha",
85+
"Programming Language :: Python :: 3.13",
86+
"Development Status :: 4 - Beta",
8687
"License :: OSI Approved :: Apache Software License",
8788
"Operating System :: OS Independent",
8889
],

wfexs_backend/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
__license__ = "Apache 2.0"
2222

2323
# https://www.python.org/dev/peps/pep-0396/
24-
__version__ = "1.0.0rc0"
24+
__version__ = "1.0.0rc1"
2525
__url__ = "https://github.com/inab/WfExS-backend"
2626
__official_name__ = "WfExS-backend"
2727

wfexs_backend/container_factories/abstract_docker_container.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -351,9 +351,7 @@ def _save(
351351
stderr=d_err,
352352
) as sp:
353353
if sp.stdout is not None:
354-
shutil.copyfileobj(
355-
cast("IO[str]", sp.stdout), d_out, length=1024 * 1024
356-
)
354+
shutil.copyfileobj(sp.stdout, d_out, length=1024 * 1024) # type: ignore[misc]
357355
d_retval = sp.wait()
358356

359357
self.logger.debug(

wfexs_backend/utils/marshalling_handling.py

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
from __future__ import absolute_import
2020

21-
from functools import partial
2221
import abc
2322
import collections.abc
2423
import copy
@@ -36,6 +35,7 @@
3635
Callable,
3736
Iterable,
3837
Mapping,
38+
MutableMapping,
3939
Optional,
4040
)
4141

@@ -51,30 +51,29 @@ def marshall_namedtuple(obj: "Any", workdir: "Optional[pathlib.Path]" = None) ->
5151
"""
5252

5353
# recurse_orig = lambda x: map(marshall_namedtuple, x)
54-
obj_is = partial(isinstance, obj)
5554
if hasattr(obj, "_marshall"):
5655
return marshall_namedtuple(obj._marshall(), workdir=workdir)
57-
elif obj_is(enum.Enum): # Enum
56+
elif isinstance(obj, enum.Enum): # Enum
5857
return {
5958
"_enum": obj.__class__.__name__,
6059
"value": obj.value,
6160
}
62-
elif obj_is(pathlib.Path):
61+
elif isinstance(obj, pathlib.Path):
6362
# Store the relative path, not the instance
6463
# Path.is_relative_to was introduced in Python 3.9
65-
is_relative_path = False
6664
if workdir is not None:
6765
# Path.is_relative_to was introduced in Python 3.9
6866
# is_relative_path = obj.is_relative_to(workdir)
6967
is_relative_path = obj == workdir or workdir in obj.parents
70-
return (
71-
obj.relative_to(workdir).as_posix() if is_relative_path else obj.as_posix()
72-
)
73-
elif obj_is(tuple) and hasattr(obj, "_fields"): # namedtuple
68+
69+
if is_relative_path:
70+
return obj.relative_to(workdir).as_posix()
71+
return obj.as_posix()
72+
elif isinstance(obj, tuple) and hasattr(obj, "_fields"): # namedtuple
7473
fields = zip(obj._fields, _recurse_m(obj, workdir))
7574
class_name = obj.__class__.__name__
7675
return dict(fields, **{"_type": class_name})
77-
elif obj_is(object) and hasattr(obj, "__dataclass_fields__"): # dataclass
76+
elif isinstance(obj, object) and hasattr(obj, "__dataclass_fields__"): # dataclass
7877
fields_m = map(
7978
lambda field: (
8079
field,
@@ -84,13 +83,13 @@ def marshall_namedtuple(obj: "Any", workdir: "Optional[pathlib.Path]" = None) ->
8483
)
8584
class_name = obj.__class__.__name__
8685
return dict(fields_m, **{"_type": class_name})
87-
elif obj_is((collections.abc.Mapping, dict)):
88-
return type(obj)(zip(obj.keys(), _recurse_m(obj.values(), workdir)))
89-
elif obj_is(collections.abc.Iterable) and not obj_is(str):
90-
return type(obj)(_recurse_m(obj, workdir))
91-
elif obj_is(abc.ABC):
86+
elif isinstance(obj, (collections.abc.Mapping, dict)):
87+
return type(obj)(zip(obj.keys(), _recurse_m(obj.values(), workdir))) # type: ignore[call-arg]
88+
elif isinstance(obj, collections.abc.Iterable) and not isinstance(obj, str):
89+
return type(obj)(_recurse_m(obj, workdir)) # type: ignore[call-arg]
90+
elif isinstance(obj, abc.ABC):
9291
return {"_instance_of": obj.__class__.__name__}
93-
elif obj_is(abc.ABCMeta):
92+
elif isinstance(obj, abc.ABCMeta):
9493
return {"_class": obj.__name__}
9594
else:
9695
return obj
@@ -120,8 +119,7 @@ def unmarshall_namedtuple(
120119

121120
# recurse_orig = lambda x, myglobals: map(lambda l: unmarshall_namedtuple(l, myglobals, workdir), x)
122121
objres = obj
123-
obj_is = partial(isinstance, obj)
124-
if obj_is((collections.abc.Mapping, dict)):
122+
if isinstance(obj, (collections.abc.Mapping, dict)):
125123
if "_enum" in obj: # originally an enum
126124
try:
127125
clazz = myglobals[obj["_enum"]]
@@ -151,7 +149,7 @@ def unmarshall_namedtuple(
151149
return clazz
152150

153151
if "_type" in obj: # originally namedtuple
154-
objn = obj.copy()
152+
objn = cast("MutableMapping[str, Any]", copy.copy(obj))
155153
theTypeName = objn.pop("_type")
156154
try:
157155
clazz = myglobals[theTypeName]
@@ -161,7 +159,7 @@ def unmarshall_namedtuple(
161159
)
162160
raise
163161
else:
164-
objn = obj
162+
objn = obj # type: ignore[assignment]
165163
clazz = type(obj)
166164
# theTypeName = clazz.__name__
167165

@@ -188,19 +186,19 @@ def unmarshall_namedtuple(
188186
m_fixes_m = getattr(clazz, "_mapping_fixes", None)
189187
if callable(m_fixes_m):
190188
c_objn = cast(
191-
"Callable[[Mapping[str, Any], Optional[pathlib.Path]], Mapping[str, Any]]",
189+
"Callable[[MutableMapping[str, Any], Optional[pathlib.Path]], MutableMapping[str, Any]]",
192190
m_fixes_m,
193191
)(c_objn, workdir)
194192

195193
# Fixes where some key was renamed along the development
196194
fixes_m = getattr(clazz, "_key_fixes", None)
197195
if callable(fixes_m):
198196
fixes = cast("Callable[[], Mapping[str, str]]", fixes_m)()
199-
c_objn_keys = map(
200-
lambda c_objn_key: fixes.get(c_objn_key, c_objn_key), c_objn.keys()
197+
c_objn_keys = list(
198+
map(lambda c_objn_key: fixes.get(c_objn_key, c_objn_key), c_objn.keys())
201199
)
202200
else:
203-
c_objn_keys = c_objn.keys()
201+
c_objn_keys = list(c_objn.keys())
204202

205203
fields_list = list(
206204
zip(c_objn_keys, _recurse_u(c_objn.values(), myglobals, workdir))
@@ -224,9 +222,9 @@ def unmarshall_namedtuple(
224222
except:
225223
logger.exception(f"Unmarshalling Error instantiating {clazz.__name__}")
226224
raise
227-
elif obj_is(collections.abc.Iterable) and not obj_is(str):
225+
elif isinstance(obj, collections.abc.Iterable) and not isinstance(obj, str):
228226
# print(type(obj))
229-
return type(obj)(_recurse_u(obj, myglobals, workdir))
227+
return type(obj)(_recurse_u(obj, myglobals, workdir)) # type: ignore[call-arg]
230228

231229
if isinstance(objres, object):
232230
if hasattr(objres, "_value_defaults_fixes") and callable(

wfexs_backend/utils/rocrate.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -398,10 +398,23 @@ def __init__(self, wfexs: "WfExSBackend"):
398398
STRSTARTS(str(?rocrateprofile), str(rocrate:))
399399
) .
400400
OPTIONAL {
401-
?rocratejson dcterms:conformsTo ?wfcrateprofile .
402-
FILTER (
403-
?wfcrateprofile = wfhprofile: || STRSTARTS(str(?wfcrateprofile), str(wfcrate:))
404-
) .
401+
{
402+
FILTER NOT EXISTS {
403+
?rocratejson dcterms:conformsTo ?somewfcrateprofile .
404+
FILTER (
405+
?somewfcrateprofile = wfhprofile: || STRSTARTS(str(?somewfcrateprofile), str(wfcrate:))
406+
) .
407+
}
408+
?rootdataset dcterms:conformsTo ?wfcrateprofile .
409+
FILTER (
410+
?wfcrateprofile = wfhprofile: || STRSTARTS(str(?wfcrateprofile), str(wfcrate:))
411+
) .
412+
} UNION {
413+
?rocratejson dcterms:conformsTo ?wfcrateprofile .
414+
FILTER (
415+
?wfcrateprofile = wfhprofile: || STRSTARTS(str(?wfcrateprofile), str(wfcrate:))
416+
) .
417+
}
405418
OPTIONAL {
406419
?rootdataset
407420
s:mainEntity ?mainentity .

wfexs_backend/utils/zipfile_path.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -372,11 +372,13 @@ def _is_child(self, path: "ZipfilePath") -> "bool":
372372
def _next(self, at: "str") -> "ZipfilePath":
373373
return self.__class__(self._root, at)
374374

375-
def is_dir(self) -> "bool":
375+
def is_dir(self, *, follow_symlinks: bool = False) -> "bool":
376376
return not self._at or self._at.endswith("/")
377377

378-
def is_file(self) -> "bool":
379-
return self.exists() and not self.is_dir()
378+
def is_file(self, *, follow_symlinks: bool = False) -> "bool":
379+
return self.exists(follow_symlinks=follow_symlinks) and not self.is_dir(
380+
follow_symlinks=follow_symlinks
381+
)
380382

381383
def exists(self, *, follow_symlinks: bool = False) -> "bool":
382384
return self._at in self._root._name_set()

wfexs_backend/wfexs_backend.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2080,7 +2080,7 @@ def cacheWorkflow(
20802080
f"Ill-formed TRS CURIE {putative_repo_url}. It should be in the format of {TRS_SCHEME_PREFIX}://id/version or {TRS_SCHEME_PREFIX}://prefix-with-slashes/id/version"
20812081
)
20822082
trs_steps = cast("MutableSequence[str]", path_steps[0:-2])
2083-
trs_steps.extend(["ga4gh", "trs", "v2", "tools"])
2083+
trs_steps.extend(["ga4gh", "trs", "v2", ""])
20842084
trs_endpoint = urllib.parse.urlunparse(
20852085
urllib.parse.ParseResult(
20862086
scheme="https",
@@ -2227,6 +2227,9 @@ def getWorkflowRepoFromTRS(
22272227
else:
22282228
workflow_id_str = workflow_id
22292229

2230+
# The base URL must end with a slash
2231+
if trs_endpoint[-1] != "/":
2232+
trs_endpoint += "/"
22302233
# Now, time to check whether it is a TRSv2
22312234
trs_endpoint_v2_meta_url = cast("URIType", trs_endpoint + "service-info")
22322235
trs_endpoint_v2_beta2_meta_url = cast("URIType", trs_endpoint + "metadata")

0 commit comments

Comments
 (0)