Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.12
1 change: 1 addition & 0 deletions docs/changes/newsfragments/474.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Drop Python 3.9 and add Python 3.14 support, upgrade codebase to follow modern syntax, bump dependencies and add ``uv`` support.
15 changes: 7 additions & 8 deletions junifer/api/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import os
import shutil
from pathlib import Path
from typing import Optional, Union

from ..api.queue_context import GnuParallelLocalAdapter, HTCondorAdapter
from ..datagrabber import BaseDataGrabber
Expand Down Expand Up @@ -122,12 +121,12 @@ def _get_storage(storage_config: dict) -> StorageLike:


def run(
workdir: Union[str, Path, dict],
workdir: str | Path | dict,
datagrabber: dict,
markers: list[dict],
storage: dict,
preprocessors: Optional[list[dict]] = None,
elements: Optional[Elements] = None,
preprocessors: list[dict] | None = None,
elements: Elements | None = None,
) -> None:
"""Run the pipeline on the selected element.

Expand Down Expand Up @@ -166,7 +165,7 @@ def run(

"""
# Conditional to handle workdir config
if isinstance(workdir, (str, Path)):
if isinstance(workdir, str | Path):
if isinstance(workdir, str):
workdir = {"workdir": Path(workdir), "cleanup": True}
else:
Expand Down Expand Up @@ -263,8 +262,8 @@ def queue(
kind: str,
jobname: str = "junifer_job",
overwrite: bool = False,
elements: Optional[Elements] = None,
**kwargs: Union[str, int, bool, dict, tuple, list],
elements: Elements | None = None,
**kwargs: str | int | bool | dict | tuple | list,
) -> None:
"""Queue a job to be executed later.

Expand Down Expand Up @@ -425,7 +424,7 @@ def reset(config: dict) -> None:

def list_elements(
datagrabber: dict,
elements: Optional[Elements] = None,
elements: Elements | None = None,
) -> str:
"""List elements of the datagrabber filtered using `elements`.

Expand Down
11 changes: 5 additions & 6 deletions junifer/api/queue_context/gnu_parallel_local_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import shutil
import textwrap
from pathlib import Path
from typing import Optional

from ...typing import Elements
from ...utils import logger, make_executable, raise_error, run_ext_cmd
Expand Down Expand Up @@ -65,11 +64,11 @@ def __init__(
job_dir: Path,
yaml_config_path: Path,
elements: Elements,
pre_run: Optional[str] = None,
pre_collect: Optional[str] = None,
env: Optional[dict[str, str]] = None,
pre_run: str | None = None,
pre_collect: str | None = None,
env: dict[str, str] | None = None,
verbose: str = "info",
verbose_datalad: Optional[str] = None,
verbose_datalad: str | None = None,
submit: bool = False,
) -> None:
"""Initialize the class."""
Expand All @@ -92,7 +91,7 @@ def __init__(
self._run_joblog_path = self._job_dir / f"run_{self._job_name}_joblog"
self._elements_file_path = self._job_dir / "elements"

def _check_env(self, env: Optional[dict[str, str]]) -> None:
def _check_env(self, env: dict[str, str] | None) -> None:
"""Check value of env parameter on init.

Parameters
Expand Down
13 changes: 6 additions & 7 deletions junifer/api/queue_context/htcondor_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import shutil
import textwrap
from pathlib import Path
from typing import Optional

from ...typing import Elements
from ...utils import logger, make_executable, raise_error, run_ext_cmd
Expand Down Expand Up @@ -83,15 +82,15 @@ def __init__(
job_dir: Path,
yaml_config_path: Path,
elements: Elements,
pre_run: Optional[str] = None,
pre_collect: Optional[str] = None,
env: Optional[dict[str, str]] = None,
pre_run: str | None = None,
pre_collect: str | None = None,
env: dict[str, str] | None = None,
verbose: str = "info",
verbose_datalad: Optional[str] = None,
verbose_datalad: str | None = None,
cpus: int = 1,
mem: str = "8G",
disk: str = "1G",
extra_preamble: Optional[str] = None,
extra_preamble: str | None = None,
collect: str = "yes",
submit: bool = False,
) -> None:
Expand Down Expand Up @@ -121,7 +120,7 @@ def __init__(
)
self._dag_path = self._job_dir / f"{self._job_name}.dag"

def _check_env(self, env: Optional[dict[str, str]]) -> None:
def _check_env(self, env: dict[str, str] | None) -> None:
"""Check value of env parameter on init.

Parameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import logging
from pathlib import Path
from typing import Optional, Union

import pytest

Expand Down Expand Up @@ -44,7 +43,7 @@ def test_GnuParallelLocalAdapter_env_shell_error() -> None:
],
)
def test_GnuParallelLocalAdapter_elements(
elements: list[Union[str, tuple]],
elements: list[str | tuple],
expected_text: str,
) -> None:
"""Test GnuParallelLocalAdapter elements().
Expand Down Expand Up @@ -76,7 +75,7 @@ def test_GnuParallelLocalAdapter_elements(
],
)
def test_GnuParallelLocalAdapter_pre_run(
pre_run: Optional[str],
pre_run: str | None,
expected_text: str,
shell: str,
) -> None:
Expand Down Expand Up @@ -114,7 +113,7 @@ def test_GnuParallelLocalAdapter_pre_run(
],
)
def test_GnuParallelLocalAdapter_pre_collect(
pre_collect: Optional[str],
pre_collect: str | None,
expected_text: str,
shell: str,
) -> None:
Expand Down
9 changes: 4 additions & 5 deletions junifer/api/queue_context/tests/test_htcondor_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import logging
from pathlib import Path
from typing import Optional, Union

import pytest

Expand Down Expand Up @@ -58,7 +57,7 @@ def test_HTCondorAdapter_collect_error() -> None:
],
)
def test_HTCondorAdapter_pre_run(
pre_run: Optional[str],
pre_run: str | None,
expected_text: str,
shell: str,
) -> None:
Expand Down Expand Up @@ -100,7 +99,7 @@ def test_HTCondorAdapter_pre_run(
],
)
def test_HTCondorAdapter_pre_collect(
pre_collect: Optional[str],
pre_collect: str | None,
expected_text: str,
collect: str,
shell: str,
Expand Down Expand Up @@ -140,7 +139,7 @@ def test_HTCondorAdapter_pre_collect(
],
)
def test_HTCondorAdapter_run_collect(
extra_preamble: Optional[str], expected_text: str
extra_preamble: str | None, expected_text: str
) -> None:
"""Test HTCondorAdapter run() and collect().

Expand Down Expand Up @@ -181,7 +180,7 @@ def test_HTCondorAdapter_run_collect(
],
)
def test_HTCondor_dag(
elements: list[Union[str, tuple]], collect: str, expected_text: str
elements: list[str | tuple], collect: str, expected_text: str
) -> None:
"""Test HTCondorAdapter dag().

Expand Down
6 changes: 3 additions & 3 deletions junifer/api/tests/test_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import logging
from contextlib import AbstractContextManager, nullcontext
from pathlib import Path
from typing import Any, Optional, Union
from typing import Any

import pytest
from nibabel.filebasedimages import ImageFileError
Expand Down Expand Up @@ -516,7 +516,7 @@ def test_queue_with_imports(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
caplog: pytest.LogCaptureFixture,
with_: Union[str, list[str]],
with_: str | list[str],
) -> None:
"""Test queue with `with` imports.

Expand Down Expand Up @@ -742,7 +742,7 @@ def test_reset_queue(
)
def test_list_elements(
datagrabber: dict[str, str],
elements: Optional[list[tuple[str, ...]]],
elements: list[tuple[str, ...]] | None,
) -> None:
"""Test elements listing.

Expand Down
29 changes: 13 additions & 16 deletions junifer/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import subprocess
import sys
from pathlib import Path
from typing import Optional, Union

import click

Expand Down Expand Up @@ -46,7 +45,7 @@


def _validate_optional_verbose(
ctx: click.Context, param: str, value: Optional[str]
ctx: click.Context, param: str, value: str | None
):
"""Validate optional verbose option.

Expand All @@ -71,9 +70,7 @@ def _validate_optional_verbose(
return _validate_verbose(ctx, param, value)


def _validate_verbose(
ctx: click.Context, param: str, value: str
) -> Union[str, int]:
def _validate_verbose(ctx: click.Context, param: str, value: str) -> str | int:
"""Validate verbose option.

Parameters
Expand Down Expand Up @@ -142,8 +139,8 @@ def cli() -> None: # pragma: no cover
def run(
filepath: click.Path,
element: tuple[str],
verbose: Union[str, int],
verbose_datalad: Optional[Union[str, int]],
verbose: str | int,
verbose_datalad: str | int | None,
) -> None:
"""Run feature extraction.

Expand Down Expand Up @@ -214,8 +211,8 @@ def run(
)
def collect(
filepath: click.Path,
verbose: Union[str, int],
verbose_datalad: Union[str, int, None],
verbose: str | int,
verbose_datalad: str | int | None,
) -> None:
"""Collect extracted features.

Expand Down Expand Up @@ -270,8 +267,8 @@ def queue(
element: tuple[str],
overwrite: bool,
submit: bool,
verbose: Union[str, int],
verbose_datalad: Union[str, int, None],
verbose: str | int,
verbose_datalad: str | int | None,
) -> None:
"""Queue feature extraction.

Expand Down Expand Up @@ -433,8 +430,8 @@ def selftest(subpkg: str) -> None:
)
def reset(
filepath: click.Path,
verbose: Union[str, int],
verbose_datalad: Union[str, int, None],
verbose: str | int,
verbose_datalad: str | int | None,
) -> None:
"""Reset generated assets.

Expand Down Expand Up @@ -487,9 +484,9 @@ def reset(
def list_elements(
filepath: click.Path,
element: tuple[str],
output_file: Optional[click.Path],
verbose: Union[str, int],
verbose_datalad: Union[str, int, None],
output_file: click.Path | None,
verbose: str | int,
verbose_datalad: str | int | None,
) -> None:
"""List elements of a dataset.

Expand Down
7 changes: 2 additions & 5 deletions junifer/cli/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import importlib.util
import sys
from pathlib import Path
from typing import Union

import pandas as pd

Expand All @@ -19,7 +18,7 @@
__all__ = ["parse_elements", "parse_yaml"]


def parse_yaml(filepath: Union[str, Path]) -> dict: # noqa: C901
def parse_yaml(filepath: str | Path) -> dict: # noqa: C901
"""Parse YAML.

Parameters
Expand Down Expand Up @@ -141,9 +140,7 @@ def parse_yaml(filepath: Union[str, Path]) -> dict: # noqa: C901
return contents


def parse_elements(
element: tuple[str, ...], config: dict
) -> Union[Elements, None]:
def parse_elements(element: tuple[str, ...], config: dict) -> Elements | None:
"""Parse elements from cli.

Parameters
Expand Down
2 changes: 1 addition & 1 deletion junifer/cli/tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
# Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL

from collections.abc import Callable
from pathlib import Path
from typing import Callable

import pytest
from click.testing import CliRunner
Expand Down
3 changes: 1 addition & 2 deletions junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
# License: AGPL

from pathlib import Path
from typing import Union

from ....api.decorators import register_datagrabber
from ....datagrabber import PatternDataladDataGrabber
Expand All @@ -29,7 +28,7 @@ class JuselessDataladAOMICID1000VBM(PatternDataladDataGrabber):

"""

def __init__(self, datadir: Union[str, Path, None] = None) -> None:
def __init__(self, datadir: str | Path | None = None) -> None:
uri = "https://gin.g-node.org/felixh/ds003097_ReproVBM"
types = ["VBM_GM"]
replacements = ["subject"]
Expand Down
3 changes: 1 addition & 2 deletions junifer/configs/juseless/datagrabbers/camcan_vbm.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
# License: AGPL

from pathlib import Path
from typing import Union

from ....api.decorators import register_datagrabber
from ....datagrabber import PatternDataladDataGrabber
Expand All @@ -30,7 +29,7 @@ class JuselessDataladCamCANVBM(PatternDataladDataGrabber):

"""

def __init__(self, datadir: Union[str, Path, None] = None) -> None:
def __init__(self, datadir: str | Path | None = None) -> None:
uri = (
"ria+http://cat_12.5.ds.inm7.de"
"#a139b26a-8406-11ea-8f94-a0369f287950"
Expand Down
Loading
Loading