Skip to content

Commit 15d8361

Browse files
committed
Merge branch 'better-testing'
* Test both Fiji-Stable and Fiji-Latest. * Test both Java 8 and Java 21 via cjdk. * Work around JPMS encapsulation woes. * Switch to uv for environment management.
2 parents f361a24 + 46437cc commit 15d8361

File tree

15 files changed

+197
-244
lines changed

15 files changed

+197
-244
lines changed

.github/workflows/build.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ jobs:
1818
matrix:
1919
os: [ubuntu-latest, windows-latest, macos-latest]
2020
python-version: ["3.9", "3.13"]
21-
java-version: ["8", "21"]
2221

2322

2423
steps:
@@ -28,11 +27,6 @@ jobs:
2827
with:
2928
python-version: ${{matrix.python-version}}
3029

31-
- uses: actions/setup-java@v3
32-
with:
33-
java-version: ${{matrix.java-version}}
34-
distribution: 'zulu'
35-
3630
- name: Install PyImageJ
3731
run: |
3832
python -m pip install --upgrade pip

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
/dist/
88
/doc/_build/
99
/src/pyimagej.egg-info/
10+
/Fiji
1011
/Fiji.app
11-
/fiji-nojre.zip
12+
/fiji-*.zip
13+
/uv.lock
1214
MANIFEST
1315
.vscode/settings.json
1416
.vscode/launch.json

Makefile

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,28 @@
11
help:
22
@echo "Available targets:\n\
33
clean - remove build files and directories\n\
4-
setup - create mamba developer environment\n\
54
lint - run code formatters and linters\n\
65
test - run automated test suite\n\
76
docs - generate documentation site\n\
87
dist - generate release archives\n\
9-
\n\
10-
Remember to 'mamba activate pyimagej-dev' first!"
8+
"
119

1210
clean:
1311
bin/clean.sh
1412

15-
setup:
16-
bin/setup.sh
17-
18-
check:
19-
@bin/check.sh
20-
21-
lint: check
13+
lint:
2214
bin/lint.sh
2315

24-
fmt: check
16+
fmt:
2517
bin/fmt.sh
2618

27-
test: check
19+
test:
2820
bin/test.sh
2921

30-
docs: check
22+
docs:
3123
cd doc && $(MAKE) html
3224

33-
dist: check clean
34-
python -m build
25+
dist: clean
26+
uv run python -m build
3527

3628
.PHONY: tests

README.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,32 +43,30 @@ PyImageJ has been tested on the following operating systems:
4343

4444
PyImageJ requires the following packages:
4545

46-
* Python >= 3.7
46+
* Python >= 3.9
4747
* [imglyb] >= 2.1.0
4848
* [jgo] >= 1.0.3
4949
* [JPype] >= 1.3.0
5050
* [labeling] >= 0.1.14
5151
* [matplotlib] \(optional, for `ij.py.show` function only)
5252
* [NumPy]
53-
* [scyjava] >= 1.8.0
53+
* [scyjava] >= 1.12.0
5454
* [xarray]
5555

5656
PyImageJ will not function properly if dependency versions are too old.
5757

58-
In addition, PyImageJ requires [OpenJDK] and [Maven] to be installed.
59-
6058
## Installation
6159

62-
On Mac and Linux, PyImageJ can be installed using [Conda]+[Mamba]. Here is how to create
63-
and activate a new conda environment with PyImageJ available:
60+
On Mac and Linux, PyImageJ can be installed using [Conda]+[Mamba]. Here is
61+
how to create and activate a new conda environment with PyImageJ available:
6462

6563
```
6664
conda install mamba -n base -c conda-forge
67-
mamba create -n pyimagej -c conda-forge pyimagej openjdk=8
65+
mamba create -n pyimagej -c conda-forge pyimagej
6866
conda activate pyimagej
6967
```
7068

71-
You can also `pip install pyimagej`, but will then need to install OpenJDK and Maven manually.
69+
Alternately, you can `pip install pyimagej`.
7270

7371
Installation time takes approximately 20 seconds. Initializing PyImageJ
7472
takes an additional ~30 seconds to ~2-3 minutes (depending on bandwidth)
@@ -150,7 +148,5 @@ For details on how to develop the PyImageJ codebase, see
150148
[NumPy]: https://numpy.org/
151149
[scyjava]: https://github.com/scijava/scyjava
152150
[xarray]: https://docs.xarray.dev/
153-
[OpenJDK]: https://en.wikipedia.org/wiki/OpenJDK
154-
[Maven]: https://maven.apache.org/
155151
[Conda]: https://conda.io/
156152
[Mamba]: https://mamba.readthedocs.io/

bin/fmt.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ dir=$(dirname "$0")
44
cd "$dir/.."
55

66
exitCode=0
7-
ruff check --fix
7+
uv run ruff check --fix
88
code=$?; test $code -eq 0 || exitCode=$code
9-
ruff format
9+
uv run ruff format
1010
code=$?; test $code -eq 0 || exitCode=$code
1111
exit $exitCode

bin/lint.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ dir=$(dirname "$0")
44
cd "$dir/.."
55

66
exitCode=0
7-
ruff check
7+
uv run ruff check
88
code=$?; test $code -eq 0 || exitCode=$code
9-
ruff format --check
9+
uv run ruff format --check
1010
code=$?; test $code -eq 0 || exitCode=$code
11-
validate-pyproject pyproject.toml
11+
uv run validate-pyproject pyproject.toml
1212
code=$?; test $code -eq 0 || exitCode=$code
1313
exit $exitCode

bin/test.sh

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,41 +7,63 @@ modes="
77
| Testing ImageJ2 + original ImageJ |--legacy=true
88
| Testing ImageJ2 standalone |--legacy=false
99
| Testing Fiji Is Just ImageJ(2) |--ij=sc.fiji:fiji
10-
| Testing locally wrapped Fiji.app |--ij=Fiji.app
10+
| Testing local Fiji-Stable |--ij=Fiji.app
11+
| Testing local Fiji-Latest |--ij=Fiji
1112
| Testing ImageJ2 version 2.10.0 |--ij=2.10.0
1213
| Testing ImageJ2 version 2.14.0 |--ij=2.14.0
1314
"
1415

1516
if [ ! -d Fiji.app ]
1617
then
17-
# No locally available Fiji.app; download one.
18-
echo "-- Downloading and unpacking Fiji.app --"
18+
# No locally available Fiji-Stable; download one.
19+
echo "-- Downloading and unpacking Fiji-Stable --"
1920
curl -fsLO https://downloads.imagej.net/fiji/stable/fiji-stable-portable-nojava.zip
2021
unzip fiji-stable-portable-nojava.zip
2122
echo
2223
fi
2324

25+
if [ ! -d Fiji ]
26+
then
27+
# No locally available Fiji-Latest; download one.
28+
echo "-- Downloading and unpacking Fiji-Latest --"
29+
curl -fsLO https://downloads.imagej.net/fiji/latest/fiji-latest-portable-nojava.zip
30+
unzip fiji-latest-portable-nojava.zip
31+
echo
32+
fi
33+
2434
echo "$modes" | while read mode
2535
do
2636
test "$mode" || continue
2737
msg="${mode%|*}|"
2838
flag=${mode##*|}
29-
echo "-------------------------------------"
30-
echo "$msg"
31-
echo "-------------------------------------"
32-
if [ $# -gt 0 ]
33-
then
34-
python -m pytest -p no:faulthandler $flag $@
35-
else
36-
python -m pytest -p no:faulthandler $flag tests
37-
fi
38-
code=$?
39-
if [ $code -ne 0 ]
40-
then
41-
# HACK: `while read` creates a subshell, which can't modify the parent
42-
# shell's variables. So we save the failure code to a temporary file.
43-
echo $code >exitCode.tmp
44-
fi
39+
for java in 8 21
40+
do
41+
# Fiji-Latest requires Java 21; skip Fiji-Latest + Java 8.
42+
echo "$msg" | grep -q Fiji-Latest && test "$java" -eq 8 && continue
43+
44+
echo "-------------------------------------"
45+
echo "$msg"
46+
printf "| < OpenJDK %2s > |\n" "$java"
47+
echo "-------------------------------------"
48+
if [ $# -gt 0 ]
49+
then
50+
uv run python -m pytest -p no:faulthandler $flag --java $java $@
51+
else
52+
uv run python -m pytest -p no:faulthandler $flag --java $java tests
53+
fi
54+
code=$?
55+
if [ $code -eq 0 ]
56+
then
57+
echo "==> TESTS PASSED with code 0"
58+
else
59+
# HACK: `while read` creates a subshell, which can't modify the parent
60+
# shell's variables. So we save the failure code to a temporary file.
61+
echo
62+
echo "==> TESTS FAILED with code $code"
63+
echo $code >exitCode.tmp
64+
fi
65+
echo
66+
done
4567
done
4668
exitCode=0
4769
if [ -f exitCode.tmp ]

conftest.py

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
import pytest
44

55
import imagej
6+
import imagej.doctor
67
from scyjava import config
78

89

910
def pytest_addoption(parser):
1011
"""
11-
Set up the command line parser for ImageJ location and headless mode
12+
Set up the command line parser for ImageJ2 location and headless mode
1213
:param parser: pytest's parser, passed in automatically
1314
:return: None
1415
"""
@@ -32,59 +33,41 @@ def pytest_addoption(parser):
3233
default=True,
3334
help="Include the original ImageJ",
3435
)
36+
parser.addoption(
37+
"--java",
38+
action="store",
39+
default=None,
40+
help="version of Java to cache and use (e.g. 8, 11, 17, 21)",
41+
)
3542

3643

3744
@pytest.fixture(scope="session")
3845
def ij(request):
3946
"""
40-
Create an ImageJ instance to be used by the whole testing environment
47+
Create an ImageJ2 gateway to be used by the whole testing environment
4148
:param request: Pytest variable passed in to fixtures
4249
"""
50+
# enable debug logging
51+
imagej.doctor.debug_to_stderr()
4352
# get test configuration
4453
ij_dir = request.config.getoption("--ij")
4554
legacy = request.config.getoption("--legacy")
4655
headless = request.config.getoption("--headless")
47-
# add the nashorn (JavaScript) endpoint if needed,
48-
# nashorn was bundled with the JDK from Java 8 to 14
49-
if capture_java_version() > 14:
56+
java_version = request.config.getoption("--java")
57+
config.set_java_constraints(fetch=True, vendor='zulu', version=java_version)
58+
# JavaScript is used in the tests. But the Nashorn engine was
59+
# dropped from the JDK at v15, so we readd it here if needed.
60+
if int(java_version) >= 15:
5061
config.endpoints.append("org.openjdk.nashorn:nashorn-core")
51-
imagej.when_imagej_starts(lambda ij: setattr(ij, "_testing", True))
52-
# initialize the ImageJ gateway
62+
imagej.when_imagej_starts(lambda ij: setattr(ij, "_java_version", java_version))
63+
# initialize the ImageJ2 gateway
5364
mode = "headless" if headless else "interactive"
5465
ij = imagej.init(ij_dir, mode=mode, add_legacy=legacy)
55-
5666
yield ij
5767

5868
ij.dispose()
5969

6070

61-
def capture_java_version() -> int:
62-
"""Capture the installed Java version.
63-
64-
This function captures the JDK version installed in the current
65-
venv without starting the JVM by parsing the Java "-version"
66-
output string.
67-
68-
:return: The major Java version (8, 11, 21 etc...).
69-
"""
70-
try:
71-
# capture the Java version string
72-
java_ver_str = subprocess.run(
73-
["java", "-version"], capture_output=True, text=True
74-
)
75-
# extract the Java version from the string
76-
java_ver = java_ver_str.stderr.split("\n")[0].split(" ")[2]
77-
java_ver = java_ver.strip('"').split(".")
78-
major_ver_arr = [int(java_ver[i]) for i in range(2)]
79-
# find major Java version
80-
if major_ver_arr[0] == 1:
81-
return major_ver_arr[1] # Java 8-10
82-
else:
83-
return major_ver_arr[0] # Java 11+
84-
except FileNotFoundError:
85-
raise RuntimeError("No Java installation found.")
86-
87-
8871
def str2bool(v):
8972
"""
9073
Convert string inputs into bool

dev-environment.yml

Lines changed: 0 additions & 56 deletions
This file was deleted.

doc/Install.md

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,8 @@
33
There are two supported ways to install PyImageJ: via
44
[conda](https://conda.io/)/[mamba](https://mamba.readthedocs.io/) or via
55
[pip](https://packaging.python.org/guides/tool-recommendations/).
6-
Although both tools are great
7-
[for different reasons](https://www.anaconda.com/blog/understanding-conda-and-pip),
8-
if you have no strong preference then we suggest using mamba because it will
9-
manage PyImageJ's non-Python dependencies:
10-
[Java](https://www.azul.com/downloads/?version=java-8-lts&package=jdk#zulu) (a.k.a. Java) and
11-
[Maven](https://maven.apache.org/install.html). If you use pip, you will need to install
12-
those two things separately.
6+
Both tools are great
7+
[for different reasons](https://www.anaconda.com/blog/understanding-conda-and-pip).
138

149
## Installing via conda/mamba
1510

0 commit comments

Comments
 (0)