diff --git a/.copier-answers.yml b/.copier-answers.yml index 36c038e..497ab90 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Do not edit - changes here will be overwritten by Copier -_commit: v0.3.0 +_commit: v0.4.2 _src_path: gh:fractal-analytics-platform/fractal-tasks-template author_email: joel.luethi@uzh.ch author_name: Joel Luethi diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml new file mode 100644 index 0000000..c444d41 --- /dev/null +++ b/.github/workflows/build_and_test.yml @@ -0,0 +1,108 @@ +name: CI (build and test) + +on: + push: + branches: ["main"] + tags: + - "*" + pull_request: + branches: ["main"] + + +jobs: + tests: + strategy: + matrix: + os: [ubuntu-22.04, macos-latest] + python-version: ["3.9", "3.10", "3.11"] + exclude: + - os: macos-latest + python-version: '3.9' + - os: macos-latest + python-version: '3.10' + name: "Core, Python ${{ matrix.python-version }}, ${{ matrix.os }}" + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: "pip" + + - name: Install package + run: python -m pip install -e .[dev] + + - name: Install some testing dependencies (hard-coded) + run: python -m pip install pytest pytest-cov devtools jsonschema requests wget pooch + + - name: Regenerate the manifest + run: python src/fractal_helper_tasks/dev/create_manifest.py + + - name: Cache Pooch folder + id: cache-pooch-folder + uses: actions/cache@v3 + with: + path: ~/.cache/pooch + key: pooch-cache + + - name: Check if manifest has changed + run: | + if [ -n "$(git diff --exit-code ./src/fractal_helper_tasks/__FRACTAL_MANIFEST__.json)" ]; then + echo "__FRACTAL_MANIFEST__.json has changed. Please run 'python src/fractal_helper_tasks/dev/create_manifest.py' and commit the changes." + exit 1 + else + echo "__FRACTAL_MANIFEST__.json has not changed." + fi + + - name: Test tasks with pytest + run: pytest --color=yes --cov --cov-report=xml --cov-report=term-missing -s --log-cli-level debug + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.3.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + slug: jluethi/fractal-helper-tasks + + deploy: + name: Deploy + needs: tests + if: success() && startsWith(github.ref, 'refs/tags/') && github.event_name != 'schedule' + runs-on: ubuntu-latest + + permissions: + # IMPORTANT: this permission is mandatory for trusted publishing on PyPi + # see https://docs.pypi.org/trusted-publishers/ + id-token: write + # This permission allows writing releases + contents: write + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: 🐍 Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.x" + + - name: 👷 Build + run: | + python -m pip install build + python -m build + + - name: 🚢 Publish to PyPI + # TODO remove the "if: false" line when the package is ready for pypi release + if: false + uses: pypa/gh-action-pypi-publish@release/v1 + + - uses: softprops/action-gh-release@v2 + with: + generate_release_notes: true + files: './dist/*' \ No newline at end of file diff --git a/.github/workflows/ci_pip.yml b/.github/workflows/ci_pip.yml deleted file mode 100644 index f0bcc4e..0000000 --- a/.github/workflows/ci_pip.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: CI (pip) - -on: - push: - branches: ["main"] - pull_request: - branches: ["main"] - - -jobs: - - tests: - strategy: - matrix: - os: [ubuntu-latest, macos-latest] - python-version: ["3.9", "3.10", "3.11"] - name: "Core, Python ${{ matrix.python-version }}, ${{ matrix.os }}" - runs-on: ${{ matrix.os }} - timeout-minutes: 30 - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - cache: "pip" - - - name: Install package - run: python -m pip install -e .[dev,test] - - - name: Install some testing dependencies (hard-coded) - run: python -m pip install pytest devtools jsonschema requests wget pooch - - - name: Cache Pooch folder - id: cache-pooch-folder - uses: actions/cache@v3 - with: - path: ~/.cache/pooch - key: pooch-cache - - - name: Test tasks with pytest - run: pytest --color=yes --cov --cov-report=xml --cov-report=term-missing -s --log-cli-level debug - - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v4.3.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - slug: jluethi/fractal-helper-tasks \ No newline at end of file diff --git a/.gitignore b/.gitignore index 13afad0..36b5e77 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +# Git ignored is sourced from https://github.com/pydev-guide/pyrepo-copier/blob/main/LICENSE # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] @@ -108,4 +109,4 @@ ENV/ # IDE settings .vscode/ -.idea/ +.idea/ \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 6924b73..4483512 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,18 +5,12 @@ build-backend = "hatchling.build" # https://hatch.pypa.io/latest/config/metadata/ [tool.hatch.version] -#path = "src/fractal_helper_tasks/__init__.py" source = "vcs" # read more about configuring hatch at: # https://hatch.pypa.io/latest/config/build/ [tool.hatch.build.targets.wheel] -only-include = ["src"] -sources = ["src"] - -# Always include the __FRACTAL_MANIFEST__.json file in the package -[tool.hatch.build] -include = ["__FRACTAL_MANIFEST__.json"] +packages = ["src/fractal_helper_tasks"] # Project metadata (see https://peps.python.org/pep-0621) @@ -33,7 +27,7 @@ authors = [ # Required Python version and dependencies requires-python = ">=3.9" dependencies = [ - "fractal-tasks-core==1.2.0" + "fractal-tasks-core==1.3.3" ] # Optional dependencies (e.g. for `pip install -e ".[dev]"`, see diff --git a/src/fractal_helper_tasks/__FRACTAL_MANIFEST__.json b/src/fractal_helper_tasks/__FRACTAL_MANIFEST__.json index 59652fa..9746921 100644 --- a/src/fractal_helper_tasks/__FRACTAL_MANIFEST__.json +++ b/src/fractal_helper_tasks/__FRACTAL_MANIFEST__.json @@ -6,6 +6,9 @@ "output_types": { "has_t": false }, + "tags": [ + "Singelton time dimension" + ], "executable_non_parallel": "drop_t_dimension.py", "meta_non_parallel": { "cpus_per_task": 2, @@ -45,6 +48,10 @@ "input_types": { "is_3D": false }, + "tags": [ + "Mixed modality", + "2D to 3D workflows" + ], "executable_parallel": "convert_2D_segmentation_to_3D.py", "meta_parallel": { "cpus_per_task": 2, @@ -122,5 +129,6 @@ } ], "has_args_schemas": true, - "args_schema_version": "pydantic_v2" + "args_schema_version": "pydantic_v2", + "authors": "Joel Luethi" } diff --git a/src/fractal_helper_tasks/dev/create_manifest.py b/src/fractal_helper_tasks/dev/create_manifest.py index c5adb16..fa0cd08 100644 --- a/src/fractal_helper_tasks/dev/create_manifest.py +++ b/src/fractal_helper_tasks/dev/create_manifest.py @@ -7,4 +7,5 @@ to the package manifest. """ PACKAGE = "fractal_helper_tasks" - create_manifest(package=PACKAGE) + AUTHORS = "Joel Luethi" + create_manifest(package=PACKAGE, authors=AUTHORS) diff --git a/src/fractal_helper_tasks/dev/task_list.py b/src/fractal_helper_tasks/dev/task_list.py index a1da4a0..797b0a1 100644 --- a/src/fractal_helper_tasks/dev/task_list.py +++ b/src/fractal_helper_tasks/dev/task_list.py @@ -8,11 +8,16 @@ executable="drop_t_dimension.py", meta={"cpus_per_task": 2, "mem": 8000}, output_types=dict(has_t=False), + tags=["Singelton time dimension"], ), ParallelTask( input_types=dict(is_3D=False), name="Convert 2D segmentation to 3D", executable="convert_2D_segmentation_to_3D.py", meta={"cpus_per_task": 2, "mem": 8000}, + tags=[ + "Mixed modality", + "2D to 3D workflows", + ], ), ] diff --git a/tests/__init__.py b/tests/__init__.py index 146b939..9cc1520 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,7 +1,7 @@ -import fractal_helper_tasks import json from pathlib import Path +import fractal_helper_tasks PACKAGE = "fractal_helper_tasks" PACKAGE_DIR = Path(fractal_helper_tasks.__file__).parent diff --git a/tests/test_valid_task_interface.py b/tests/test_valid_task_interface.py index 6f1885e..590db68 100644 --- a/tests/test_valid_task_interface.py +++ b/tests/test_valid_task_interface.py @@ -1,7 +1,6 @@ import json import subprocess from shlex import split as shlex_split -from subprocess import PIPE import pytest from devtools import debug @@ -16,8 +15,7 @@ def validate_command(cmd: str): debug(cmd) result = subprocess.run( # nosec shlex_split(cmd), - stdout=PIPE, - stderr=PIPE, + capture_output=True, ) # The command must always fail, since tmp_file_args includes invalid # arguments @@ -25,13 +23,13 @@ def validate_command(cmd: str): stderr = result.stderr.decode() debug(stderr) - # Valid stderr includes pydantic.error_wrappers.ValidationError (type + # Valid stderr includes pydantic.v1.error_wrappers.ValidationError (type # match between model and function, but tmp_file_args has wrong arguments) - # assert "pydantic.v1.error_wrappers.ValidationError" in stderr + assert "ValidationError" in stderr - # # Valid stderr must include a mention of "unexpected keyword arguments", - # # because we are including some invalid arguments - # assert "unexpected keyword arguments" in stderr + # Valid stderr must include a mention of "Unexpected keyword argument", + # because we are including some invalid arguments + assert "Unexpected keyword argument" in stderr # # Invalid stderr includes ValueError # assert "ValueError" not in stderr @@ -46,7 +44,7 @@ def test_task_interface(task, tmp_path): tmp_file_args = str(tmp_path / "args.json") tmp_file_metadiff = str(tmp_path / "metadiff.json") with open(tmp_file_args, "w") as fout: - args = dict(wrong_arg_1=123, wrong_arg_2=[1, 2, 3]) + args = {"wrong_arg_1": 123, "wrong_arg_2": [1, 2, 3]} json.dump(args, fout, indent=4) for key in ["executable_non_parallel", "executable_parallel"]: