Skip to content

Commit f17c026

Browse files
committed
Merge tag '1.11.0'
1.11.0 (July 31, 2024) New minor release to start the 1.11.x series. The major changes include: - a deprecation to T1w-only based template processing - addition of a new dependency ``acres`` for accessing package data However, this is still backwards compatible with the 1.10.x series. * MAINT: Depend on acres for data access * ENH: Add PrepareDerivative/SaveDerivative interfaces (#885) * ENH: Make template dimensions support T2w as well (#879) * ENH: Modify FSSource to output T2 (#868) * FIX: Set cal_max in the NIfTI header for visualization after ``IntensityClip`` (#878) * FIX: Remove accidental MRIQC dependency, allow app config to be passed to workflow plugin (#876) * TEST: Fix plugin invocation, use an initializer that can be verified (#880)
2 parents f765e53 + f972df5 commit f17c026

File tree

7 files changed

+26
-172
lines changed

7 files changed

+26
-172
lines changed

CHANGES.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
1.11.0 (July 31, 2024)
2+
======================
3+
New minor release to start the 1.11.x series.
4+
5+
The major changes include:
6+
- a deprecation to T1w-only based template processing
7+
- addition of a new dependency ``acres`` for accessing package data
8+
9+
However, this is still backwards compatible with the 1.10.x series.
10+
11+
* MAINT: Depend on acres for data access
12+
* ENH: Add PrepareDerivative/SaveDerivative interfaces (#885)
13+
* ENH: Make template dimensions support T2w as well (#879)
14+
* ENH: Modify FSSource to output T2 (#868)
15+
* FIX: Set cal_max in the NIfTI header for visualization after ``IntensityClip`` (#878)
16+
* FIX: Remove accidental MRIQC dependency, allow app config to be passed to workflow plugin (#876)
17+
* TEST: Fix plugin invocation, use an initializer that can be verified (#880)
18+
19+
120
1.10.2 (June 10, 2024)
221
======================
322
Bug-fix release in the 1.10.x series

docs/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
acres
12
attrs
23
furo
34
importlib_resources

niworkflows/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
"""NeuroImaging Workflows (NIWorkflows) is a selection of image processing workflows."""
44
import logging
55

6+
from acres import Loader
7+
68
from .__about__ import __packagename__, __copyright__, __credits__
7-
from .data import Loader
89
try:
910
from ._version import __version__
1011
except ImportError: # pragma: no cover

niworkflows/data/__init__.py

Lines changed: 1 addition & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -7,176 +7,8 @@
77
.. automethod:: load.as_path
88
99
.. automethod:: load.cached
10-
11-
.. autoclass:: Loader
1210
"""
13-
from __future__ import annotations
14-
15-
import atexit
16-
import os
17-
from contextlib import AbstractContextManager, ExitStack
18-
from functools import cached_property
19-
from pathlib import Path
20-
from types import ModuleType
21-
from typing import Union
22-
23-
try:
24-
from functools import cache
25-
except ImportError: # PY38
26-
from functools import lru_cache as cache
27-
28-
try: # Prefer backport to leave consistency to dependency spec
29-
from importlib_resources import as_file, files
30-
except ImportError:
31-
from importlib.resources import as_file, files # type: ignore
32-
33-
try: # Prefer stdlib so Sphinx can link to authoritative documentation
34-
from importlib.resources.abc import Traversable
35-
except ImportError:
36-
from importlib_resources.abc import Traversable
37-
38-
__all__ = ["load"]
39-
40-
41-
class Loader:
42-
"""A loader for package files relative to a module
43-
44-
This class wraps :mod:`importlib.resources` to provide a getter
45-
function with an interpreter-lifetime scope. For typical packages
46-
it simply passes through filesystem paths as :class:`~pathlib.Path`
47-
objects. For zipped distributions, it will unpack the files into
48-
a temporary directory that is cleaned up on interpreter exit.
49-
50-
This loader accepts a fully-qualified module name or a module
51-
object.
52-
53-
Expected usage::
54-
55-
'''Data package
56-
57-
.. autofunction:: load_data
58-
59-
.. automethod:: load_data.readable
60-
61-
.. automethod:: load_data.as_path
62-
63-
.. automethod:: load_data.cached
64-
'''
65-
66-
from niworkflows.data import Loader
67-
68-
load_data = Loader(__package__)
69-
70-
:class:`~Loader` objects implement the :func:`callable` interface
71-
and generate a docstring, and are intended to be treated and documented
72-
as functions.
73-
74-
For greater flexibility and improved readability over the ``importlib.resources``
75-
interface, explicit methods are provided to access resources.
76-
77-
+---------------+----------------+------------------+
78-
| On-filesystem | Lifetime | Method |
79-
+---------------+----------------+------------------+
80-
| `True` | Interpreter | :meth:`cached` |
81-
+---------------+----------------+------------------+
82-
| `True` | `with` context | :meth:`as_path` |
83-
+---------------+----------------+------------------+
84-
| `False` | n/a | :meth:`readable` |
85-
+---------------+----------------+------------------+
86-
87-
It is also possible to use ``Loader`` directly::
88-
89-
from niworkflows.data import Loader
90-
91-
Loader(other_package).readable('data/resource.ext').read_text()
92-
93-
with Loader(other_package).as_path('data') as pkgdata:
94-
# Call function that requires full Path implementation
95-
func(pkgdata)
96-
97-
# contrast to
98-
99-
from importlib_resources import files, as_file
100-
101-
files(other_package).joinpath('data/resource.ext').read_text()
102-
103-
with as_file(files(other_package) / 'data') as pkgdata:
104-
func(pkgdata)
105-
106-
.. automethod:: readable
107-
108-
.. automethod:: as_path
109-
110-
.. automethod:: cached
111-
"""
112-
113-
def __init__(self, anchor: Union[str, ModuleType]):
114-
self._anchor = anchor
115-
self.files = files(anchor)
116-
self.exit_stack = ExitStack()
117-
atexit.register(self.exit_stack.close)
118-
# Allow class to have a different docstring from instances
119-
self.__doc__ = self._doc
120-
121-
@cached_property
122-
def _doc(self):
123-
"""Construct docstring for instances
124-
125-
Lists the public top-level paths inside the location, where
126-
non-public means has a `.` or `_` prefix or is a 'tests'
127-
directory.
128-
"""
129-
top_level = sorted(
130-
os.path.relpath(p, self.files) + "/"[: p.is_dir()]
131-
for p in self.files.iterdir()
132-
if p.name[0] not in (".", "_") and p.name != "tests"
133-
)
134-
doclines = [
135-
f"Load package files relative to ``{self._anchor}``.",
136-
"",
137-
"This package contains the following (top-level) files/directories:",
138-
"",
139-
*(f"* ``{path}``" for path in top_level),
140-
]
141-
142-
return "\n".join(doclines)
143-
144-
def readable(self, *segments) -> Traversable:
145-
"""Provide read access to a resource through a Path-like interface.
146-
147-
This file may or may not exist on the filesystem, and may be
148-
efficiently used for read operations, including directory traversal.
149-
150-
This result is not cached or copied to the filesystem in cases where
151-
that would be necessary.
152-
"""
153-
return self.files.joinpath(*segments)
154-
155-
def as_path(self, *segments) -> AbstractContextManager[Path]:
156-
"""Ensure data is available as a :class:`~pathlib.Path`.
157-
158-
This method generates a context manager that yields a Path when
159-
entered.
160-
161-
This result is not cached, and any temporary files that are created
162-
are deleted when the context is exited.
163-
"""
164-
return as_file(self.files.joinpath(*segments))
165-
166-
@cache
167-
def cached(self, *segments) -> Path:
168-
"""Ensure data is available as a :class:`~pathlib.Path`.
169-
170-
Any temporary files that are created remain available throughout
171-
the duration of the program, and are deleted when Python exits.
172-
173-
Results are cached so that multiple calls do not unpack the same
174-
data multiple times, but the cache is sensitive to the specific
175-
argument(s) passed.
176-
"""
177-
return self.exit_stack.enter_context(as_file(self.files.joinpath(*segments)))
178-
179-
__call__ = cached
18011

12+
from acres import Loader
18113

18214
load = Loader(__package__)

niworkflows/interfaces/tests/data/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
33
.. autofunction:: load_test_data
44
"""
5-
from ....data import Loader
5+
from acres import Loader
66

77
load_test_data = Loader(__package__)

niworkflows/tests/data/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
33
.. autofunction:: load_test_data
44
"""
5-
from ...data import Loader
5+
from acres import Loader
66

77
load_test_data = Loader(__package__)

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ classifiers = [
2424
"Topic :: Scientific/Engineering :: Image Recognition",
2525
]
2626
dependencies = [
27+
"acres",
2728
"attrs",
2829
"importlib_resources >= 5.7; python_version < '3.11'",
2930
"jinja2",

0 commit comments

Comments
 (0)