%global srcname fsl-pyfeeds %global modname pyfeeds Name: fsl-pyfeeds Version: 1.4.1 Release: 1%{?dist} Summary: FEEDS - the FSL Evaluation and Example Data Suite test runner # Verified first-hand 2026-09-28: the repository ships LICENSE (full Apache 2.0) # and COPYRIGHT, and FSL's own conda recipe is one of only 7 of 135 that declares # a licence at all -- license: Apache-2.0, license_family: Apache, # license_file: LICENSE. Both are installed as %%license below. License: Apache-2.0 URL: https://git.fmrib.ox.ac.uk/fsl/pyfeeds Source0: %{url}/-/archive/%{version}/%{modname}-%{version}.tar.gz#/%{srcname}-%{version}.tar.gz BuildArch: noarch BuildRequires: python3-devel BuildRequires: pyproject-rpm-macros # Upstream's mock tests -- pyfeeds/tests/mock_tests/tests/test*/feedsRun -- carry # "#!/usr/bin/env python", and a Fedora buildroot has python3 but no `python`. # Without this, build 11045931 failed %%check with the feedsRun log reading # env: 'python': No such file or directory # and the test that caught it was the only one of upstream's three that asserts an # output file exists. See the changelog: the other two pass whether or not a single # test ran. BuildRequires: python-unversioned-command # pyfeeds is the framework, not the tests. It runs a suite of FSL test cases and # compares their output against benchmark data, so FSL itself is what you point it # at rather than something it links -- hence Recommends, not Requires: pyfeeds is # useful on its own for writing and validating test definitions, and its own test # suite (run in %%check) passes with no FSL present. Recommends: fsl %description pyfeeds is the current implementation of FEEDS, the suite FSL uses to verify an installation: it runs test cases, collects their outputs and compares them against benchmark data, reporting per-test pass/fail. WHAT YOU NEED BESIDES THIS PACKAGE. The test cases and their data live in a separate repository, fsl/pyfeeds-tests, which is NOT packaged here and cannot be, for two reasons worth knowing before you go looking: * Its NIfTI data is stored in Git LFS (.gitattributes tracks *.nii.gz), so a release tarball from the tag contains 130-byte pointer files rather than images. It has to be obtained with a git-lfs clone: git clone --branch 2606.0 https://git.fmrib.ox.ac.uk/fsl/pyfeeds-tests.git The LFS payload at tag 2606.0 is 223 objects and about 75 MiB, all of it under gpu_test/ and unit_tests/. * Upstream's own README states that many of the tests depend on benchmark data "hosted internally at FMRIB, and thus cannot be executed outside of the FMRIB computing system". The suites that CAN run elsewhere are unit_tests, which carries its own inputs, and gpu_test, which additionally needs CUDA hardware. So on a machine outside FMRIB this package plus the unit_tests suite gives a real end-to-end check of the installed FSL binaries -- bet, flirt, fugue, film_gls, fdt, applyxfm4D, randomise_parallel and the fslStartup/misc C utilities -- and the rest of FEEDS is not reachable without FMRIB's data. %prep %autosetup -p1 -n %{modname}-%{version} # pyproject.toml declares version dynamic with [tool.setuptools_scm], and a tag # archive has no .git, so setuptools-scm resolves 0.0.0 or fails outright. %global _scm_env SETUPTOOLS_SCM_PRETEND_VERSION_FOR_FSL_PYFEEDS=%{version} SETUPTOOLS_SCM_PRETEND_VERSION=%{version} %generate_buildrequires export %{_scm_env} %pyproject_buildrequires -x test %build export %{_scm_env} %pyproject_wheel %install export %{_scm_env} %pyproject_install # NOT -l. Upstream uses the pre-PEP-639 spelling, license = {text = "Apache # License Version 2.0"}, so the wheel carries no License-File entry and # %%pyproject_save_files -l fails with a ValueError. Install the two files # explicitly instead; the same shape bit eddy_qc, get_standard and pyfix. %pyproject_save_files %{modname} %check # The bundled suite is self-contained -- pyfeeds/tests/mock_tests ships its own # inputData and benchmarkData -- so this exercises the comparison engine, which is # the part of pyfeeds that can be wrong in a way that silently passes real tests. # addopts in pyproject.toml carries --cov, which needs pytest-cov and turns a # missing plugin into a collection error; -o addopts= drops it. export %{_scm_env} %pytest -o addopts= -p no:cacheprovider # The console script is the whole interface, and %%pyproject_check_import would not # catch a broken entry point. test -x %{buildroot}%{_bindir}/pyfeeds PYTHONPATH=%{buildroot}%{python3_sitelib} %{buildroot}%{_bindir}/pyfeeds --help > _help.txt grep -qE '\brun\b' _help.txt # Assert the version it reports is ours, not setuptools-scm's 0.0.0 fallback. A # 0.0.0 build installs and runs, and every consumer floor against it is vacuous -- # the same defect shape as afnipy declaring 0.0.1 against rpm 26.2.09. PYTHONPATH=%{buildroot}%{python3_sitelib} %{python3} -c \ 'from importlib.metadata import version; v=version("fsl-pyfeeds"); print("pyfeeds dist version:", v); assert v == "%{version}", v' %files -n %{name} -f %{pyproject_files} %license LICENSE COPYRIGHT %doc README.md CHANGELOG.rst doc/ %{_bindir}/pyfeeds %changelog * Mon Sep 28 2026 Morgan Hough - 1.4.1-1 - Initial package. Morgan: FEEDS is what system-tests the FSL packages, and we should have run it somewhere against a real install. - Two things about FEEDS that are not obvious and change what "run it" can mean, both established from upstream on 2026-09-28: * The tests are a SEPARATE repository (fsl/pyfeeds-tests) whose NIfTI data is in Git LFS -- .gitattributes tracks *.nii.gz -- so a tag archive yields pointer files, not images. 223 objects, ~75 MiB at tag 2606.0, all under gpu_test/ and unit_tests/. Not packaged here; a git-lfs clone is the only way to get it. * Upstream's README says plainly that many tests need benchmark data "hosted internally at FMRIB, and thus cannot be executed outside of the FMRIB computing system". So the reachable suites off-site are unit_tests (self-contained) and gpu_test (needs CUDA). That is a limit of the suite, not of our packaging, and it is recorded in %%description so nobody rediscovers it. - Licence is one of the good ones: LICENSE (full Apache 2.0) and COPYRIGHT are both in the repo, and FSL's conda recipe for it is one of only 7 of 135 that declares a licence at all. Both files ship as %%license. - Three traps handled, each already seen elsewhere in this stack: setuptools-scm with no .git needs SETUPTOOLS_SCM_PRETEND_VERSION; the pre-PEP-639 license = {text = ...} spelling makes %%pyproject_save_files -l raise ValueError, so the licence files are listed explicitly; and addopts in pyproject.toml carries --cov, dropped with -o addopts=. - %%check runs upstream's own mock_tests, which ship their own input and benchmark data, so the comparison engine is exercised without FSL present. It also asserts the reported distribution version is 1.4.1 rather than setuptools-scm's 0.0.0 fallback -- a 0.0.0 build installs, runs, and makes every version floor against it vacuous. - Recommends rather than Requires fsl: pyfeeds is the runner, FSL is what you aim it at. - FIRST BUILD FAILED and the cause is worth recording. 11045931 died in %%check on test_pyfeeds_different_image_formats. Reproduced in a mock chroot and read the per-test log rather than guessing: `env: 'python': No such file or directory`. Upstream's mock tests use "#!/usr/bin/env python" and a Fedora buildroot has python3 but no `python`, so every mock test errored instantly. Fixed by adding BuildRequires: python-unversioned-command -- which makes the real test pass instead of deselecting it. Verified: 27 passed in the chroot afterwards. - WORTH KNOWING ABOUT UPSTREAM'S SUITE, and a candidate for the upstream report: of its three integration tests, two (test_pyfeeds_run_mock_tests and test_pyfeeds_run_mock_tests_fslsub) only call main() and assert nothing about the outcome, so they PASSED while every mock test inside them errored. Only the third, which asserts an output file exists, failed. Two of three tests were vacuous exactly when it mattered -- the same shape as the checks that have failed open on us here.