Skip to content

Commit

Permalink
Merge pull request #125 from inab/full_circle
Browse files Browse the repository at this point in the history
Release 1.0.0rc1
  • Loading branch information
jmfernandez authored Oct 16, 2024
2 parents 1564bc3 + c869d35 commit 6ab6fd1
Show file tree
Hide file tree
Showing 16 changed files with 455 additions and 89 deletions.
17 changes: 8 additions & 9 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11", "3.12" ]
python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13" ]
name: Pre-commit python ${{ matrix.python-version }}
steps:
- uses: actions/checkout@v4
Expand All @@ -33,16 +33,15 @@ jobs:
with:
files: requirements.txt

- name: 'Install requirements (standard)'
if: ${{ matrix.python-version != '3.6' && steps.changed-requirements-txt.outputs.any_changed == 'true' }}
- name: 'Install requirements (standard or constraints ${{ matrix.python-version }})'
if: ${{ matrix.python-version != '3.6' }}
run: |
pip install --upgrade pip wheel
pip install -r requirements.txt
- name: 'Install requirements (constraints)'
if: ${{ matrix.python-version != '3.6' && steps.changed-requirements-txt.outputs.any_changed != 'true' }}
run: |
pip install --upgrade pip wheel
pip install -r requirements.txt -c constraints-${{ matrix.python-version }}.txt
if [ ${{ steps.changed-requirements-txt.outputs.any_changed }} != 'true' ] && [ -f constraints-${{ matrix.python-version }}.txt ] ; then
pip install -r requirements.txt -c constraints-${{ matrix.python-version }}.txt
else
pip install -r requirements.txt
fi
#- name: 'Install requirements (custom Python ${{ matrix.python-version }})'
# if: ${{ matrix.python-version == '3.6' }}
# run: |
Expand Down
5 changes: 3 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ keywords:
license: Apache-2.0
message: "If you use this software, please cite it using these metadata."
repository-code: "https://github.com/inab/WfExS-backend"
repository-artifact: "https://github.com/inab/WfExS-backend/pkgs/container/wfexs-backend"
type: software
title: "WfExS-backend"
version: 1.0.0rc0
date-released: "2024-08-07"
version: 1.0.0rc1
date-released: "2024-10-16"
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ Visit the [Zenodo record](https://doi.org/10.5281/zenodo.6567591) for the latest

### Presentations and outreach

Additional present and future list of references is hosted at [WfExS-backend ReadTheDocs outreach](https://wfexs-backend.readthedocs.io/en/latest/outreach.html).

Paula Iborra, José M. Fernández, Salvador Capella-Gutierrez (2024):
[**Onboarding Snakemake: Progress towards WfExS-backend integration**](https://doi.org/10.7490/f1000research.1119725.1).
_F1000Research_ **13**(ELIXIR):551 (poster)
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Development Status :: 3 - Alpha",
"Programming Language :: Python :: 3.13",
"Development Status :: 4 - Beta",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
],
Expand Down
2 changes: 1 addition & 1 deletion wfexs_backend/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
__license__ = "Apache 2.0"

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,9 +351,7 @@ def _save(
stderr=d_err,
) as sp:
if sp.stdout is not None:
shutil.copyfileobj(
cast("IO[str]", sp.stdout), d_out, length=1024 * 1024
)
shutil.copyfileobj(sp.stdout, d_out, length=1024 * 1024) # type: ignore[misc]
d_retval = sp.wait()

self.logger.debug(
Expand Down
50 changes: 24 additions & 26 deletions wfexs_backend/utils/marshalling_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

from __future__ import absolute_import

from functools import partial
import abc
import collections.abc
import copy
Expand All @@ -36,6 +35,7 @@
Callable,
Iterable,
Mapping,
MutableMapping,
Optional,
)

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

# recurse_orig = lambda x: map(marshall_namedtuple, x)
obj_is = partial(isinstance, obj)
if hasattr(obj, "_marshall"):
return marshall_namedtuple(obj._marshall(), workdir=workdir)
elif obj_is(enum.Enum): # Enum
elif isinstance(obj, enum.Enum): # Enum
return {
"_enum": obj.__class__.__name__,
"value": obj.value,
}
elif obj_is(pathlib.Path):
elif isinstance(obj, pathlib.Path):
# Store the relative path, not the instance
# Path.is_relative_to was introduced in Python 3.9
is_relative_path = False
if workdir is not None:
# Path.is_relative_to was introduced in Python 3.9
# is_relative_path = obj.is_relative_to(workdir)
is_relative_path = obj == workdir or workdir in obj.parents
return (
obj.relative_to(workdir).as_posix() if is_relative_path else obj.as_posix()
)
elif obj_is(tuple) and hasattr(obj, "_fields"): # namedtuple

if is_relative_path:
return obj.relative_to(workdir).as_posix()
return obj.as_posix()
elif isinstance(obj, tuple) and hasattr(obj, "_fields"): # namedtuple
fields = zip(obj._fields, _recurse_m(obj, workdir))
class_name = obj.__class__.__name__
return dict(fields, **{"_type": class_name})
elif obj_is(object) and hasattr(obj, "__dataclass_fields__"): # dataclass
elif isinstance(obj, object) and hasattr(obj, "__dataclass_fields__"): # dataclass
fields_m = map(
lambda field: (
field,
Expand All @@ -84,13 +83,13 @@ def marshall_namedtuple(obj: "Any", workdir: "Optional[pathlib.Path]" = None) ->
)
class_name = obj.__class__.__name__
return dict(fields_m, **{"_type": class_name})
elif obj_is((collections.abc.Mapping, dict)):
return type(obj)(zip(obj.keys(), _recurse_m(obj.values(), workdir)))
elif obj_is(collections.abc.Iterable) and not obj_is(str):
return type(obj)(_recurse_m(obj, workdir))
elif obj_is(abc.ABC):
elif isinstance(obj, (collections.abc.Mapping, dict)):
return type(obj)(zip(obj.keys(), _recurse_m(obj.values(), workdir))) # type: ignore[call-arg]
elif isinstance(obj, collections.abc.Iterable) and not isinstance(obj, str):
return type(obj)(_recurse_m(obj, workdir)) # type: ignore[call-arg]
elif isinstance(obj, abc.ABC):
return {"_instance_of": obj.__class__.__name__}
elif obj_is(abc.ABCMeta):
elif isinstance(obj, abc.ABCMeta):
return {"_class": obj.__name__}
else:
return obj
Expand Down Expand Up @@ -120,8 +119,7 @@ def unmarshall_namedtuple(

# recurse_orig = lambda x, myglobals: map(lambda l: unmarshall_namedtuple(l, myglobals, workdir), x)
objres = obj
obj_is = partial(isinstance, obj)
if obj_is((collections.abc.Mapping, dict)):
if isinstance(obj, (collections.abc.Mapping, dict)):
if "_enum" in obj: # originally an enum
try:
clazz = myglobals[obj["_enum"]]
Expand Down Expand Up @@ -151,7 +149,7 @@ def unmarshall_namedtuple(
return clazz

if "_type" in obj: # originally namedtuple
objn = obj.copy()
objn = cast("MutableMapping[str, Any]", copy.copy(obj))
theTypeName = objn.pop("_type")
try:
clazz = myglobals[theTypeName]
Expand All @@ -161,7 +159,7 @@ def unmarshall_namedtuple(
)
raise
else:
objn = obj
objn = obj # type: ignore[assignment]
clazz = type(obj)
# theTypeName = clazz.__name__

Expand All @@ -188,19 +186,19 @@ def unmarshall_namedtuple(
m_fixes_m = getattr(clazz, "_mapping_fixes", None)
if callable(m_fixes_m):
c_objn = cast(
"Callable[[Mapping[str, Any], Optional[pathlib.Path]], Mapping[str, Any]]",
"Callable[[MutableMapping[str, Any], Optional[pathlib.Path]], MutableMapping[str, Any]]",
m_fixes_m,
)(c_objn, workdir)

# Fixes where some key was renamed along the development
fixes_m = getattr(clazz, "_key_fixes", None)
if callable(fixes_m):
fixes = cast("Callable[[], Mapping[str, str]]", fixes_m)()
c_objn_keys = map(
lambda c_objn_key: fixes.get(c_objn_key, c_objn_key), c_objn.keys()
c_objn_keys = list(
map(lambda c_objn_key: fixes.get(c_objn_key, c_objn_key), c_objn.keys())
)
else:
c_objn_keys = c_objn.keys()
c_objn_keys = list(c_objn.keys())

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

if isinstance(objres, object):
if hasattr(objres, "_value_defaults_fixes") and callable(
Expand Down
21 changes: 17 additions & 4 deletions wfexs_backend/utils/rocrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,10 +398,23 @@ def __init__(self, wfexs: "WfExSBackend"):
STRSTARTS(str(?rocrateprofile), str(rocrate:))
) .
OPTIONAL {
?rocratejson dcterms:conformsTo ?wfcrateprofile .
FILTER (
?wfcrateprofile = wfhprofile: || STRSTARTS(str(?wfcrateprofile), str(wfcrate:))
) .
{
FILTER NOT EXISTS {
?rocratejson dcterms:conformsTo ?somewfcrateprofile .
FILTER (
?somewfcrateprofile = wfhprofile: || STRSTARTS(str(?somewfcrateprofile), str(wfcrate:))
) .
}
?rootdataset dcterms:conformsTo ?wfcrateprofile .
FILTER (
?wfcrateprofile = wfhprofile: || STRSTARTS(str(?wfcrateprofile), str(wfcrate:))
) .
} UNION {
?rocratejson dcterms:conformsTo ?wfcrateprofile .
FILTER (
?wfcrateprofile = wfhprofile: || STRSTARTS(str(?wfcrateprofile), str(wfcrate:))
) .
}
OPTIONAL {
?rootdataset
s:mainEntity ?mainentity .
Expand Down
8 changes: 5 additions & 3 deletions wfexs_backend/utils/zipfile_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,11 +372,13 @@ def _is_child(self, path: "ZipfilePath") -> "bool":
def _next(self, at: "str") -> "ZipfilePath":
return self.__class__(self._root, at)

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

def is_file(self) -> "bool":
return self.exists() and not self.is_dir()
def is_file(self, *, follow_symlinks: bool = False) -> "bool":
return self.exists(follow_symlinks=follow_symlinks) and not self.is_dir(
follow_symlinks=follow_symlinks
)

def exists(self, *, follow_symlinks: bool = False) -> "bool":
return self._at in self._root._name_set()
Expand Down
5 changes: 4 additions & 1 deletion wfexs_backend/wfexs_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -2080,7 +2080,7 @@ def cacheWorkflow(
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"
)
trs_steps = cast("MutableSequence[str]", path_steps[0:-2])
trs_steps.extend(["ga4gh", "trs", "v2", "tools"])
trs_steps.extend(["ga4gh", "trs", "v2", ""])
trs_endpoint = urllib.parse.urlunparse(
urllib.parse.ParseResult(
scheme="https",
Expand Down Expand Up @@ -2227,6 +2227,9 @@ def getWorkflowRepoFromTRS(
else:
workflow_id_str = workflow_id

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

0 comments on commit 6ab6fd1

Please sign in to comment.