Skip to content

Commit

Permalink
Merge pull request #320 from imagej/test-java-21
Browse files Browse the repository at this point in the history
CI: Test Java 21
  • Loading branch information
gselzer authored Dec 13, 2024
2 parents 8fb1df2 + 6a5179d commit bb8e4f1
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 94 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ env:

jobs:
test-pip:
name: ${{ matrix.platform }} (python ${{ matrix.python-version }})
name: ${{ matrix.platform }} (python ${{ matrix.python-version }}, java ${{matrix.java-version}})
runs-on: ${{ matrix.platform }}
strategy:
matrix:
platform: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.9', '3.12']
java-version: ['8', '21']

steps:
- uses: actions/checkout@v2
Expand All @@ -33,10 +34,10 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Set up Java 8
- name: Set up Java ${{ matrix.java-version }}
uses: actions/setup-java@v3
with:
java-version: '8'
java-version: ${{matrix.java-version}}
distribution: 'zulu'

- name: Setup Qt libraries
Expand Down
69 changes: 0 additions & 69 deletions scripts/examples/Example_Script.js

This file was deleted.

71 changes: 71 additions & 0 deletions scripts/examples/Example_Script.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#@ boolean (label="boolean") pBoolean
#@ byte (label="byte") pByte
#@ char (label="char") pChar
#@ double (label="double") pDouble
#@ float (label="float") pFloat
#@ int (label="int") pInt
#@ long (label="long") pLong
#@ short (label="short") pShort
#@ Boolean (label="Boolean") oBoolean
#@ Byte (label="Byte") oByte
#@ Character (label="Character") oCharacter
#@ Double (label="Double") oDouble
#@ Float (label="Float") oFloat
#@ Integer (label="Integer") oInteger
#@ Long (label="Long") oLong
#@ Short (label="Short") oShort
#@ int (min=0, max=1000) boundedInteger
#@ double (min=0.2, max=1000.7, stepSize=12.34) boundedDouble
#@ BigInteger bigInteger
#@ BigDecimal bigDecimal
#@ String string
#@ File file
# Colors aren't supported - see https://github.com/imagej/napari-imagej/issues/62
# #@ ColorRGB color
#@output String result

# A Jython script exercising various parameter types.
# It is the duty of the scripting framework to harvest
# the parameter values from the user, and then display
# the 'result' output parameter, based on its type.

from java.lang import StringBuilder

sb = StringBuilder()

sb.append("Widgets Jython results:\n")

sb.append("\n")
sb.append("\tboolean = " + str(pBoolean) + "\n")
sb.append("\tbyte = " + str(pByte) + "\n")
sb.append("\tchar = " + "'" + str(pChar) + "'\n")
sb.append("\tdouble = " + str(pDouble) + "\n")
sb.append("\tfloat = " + str(pFloat) + "\n")
sb.append("\tint = " + str(pInt) + "\n")
sb.append("\tlong = " + str(pLong) + "\n")
sb.append("\tshort = " + str(pShort) + "\n")

sb.append("\n")
sb.append("\tBoolean = " + str(oBoolean) + "\n")
sb.append("\tByte = " + str(oByte) + "\n")
sb.append("\tCharacter = " + "'" + str(oCharacter) + "'\n")
sb.append("\tDouble = " + str(oDouble) + "\n")
sb.append("\tFloat = " + str(oFloat) + "\n")
sb.append("\tInteger = " + str(oInteger) + "\n")
sb.append("\tLong = " + str(oLong) + "\n")
sb.append("\tShort = " + str(oShort) + "\n")

sb.append("\n")
sb.append("\tbounded integer = " + str(boundedInteger) + "\n")
sb.append("\tbounded double = " + str(boundedDouble) + "\n")

sb.append("\n")
sb.append("\tBigInteger = " + str(bigInteger) + "\n")
sb.append("\tBigDecimal = " + str(bigDecimal) + "\n")
sb.append("\tString = " + str(string) + "\n")
sb.append("\tFile = " + str(file) + "\n")
# Colors aren't supported - see https://github.com/imagej/napari-imagej/issues/62
# sb.append("\tcolor = " + color + "\n")

result = sb.toString()

18 changes: 18 additions & 0 deletions src/napari_imagej/types/widget_mappings.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from typing import Callable, Dict, Optional, Union, get_args, get_origin

from jpype import JByte, JDouble, JFloat, JInt, JLong, JShort
from napari.layers import Image

from napari_imagej.java import jc
Expand Down Expand Up @@ -70,14 +71,31 @@ def _numeric_type_preference(
) -> Optional[Union[type, str]]:
if issubclass(item.getType(), jc.NumericType):
return numeric_type_widget_for(item.getType())
return None


@_widget_preference
def _number_preference(
item: "jc.ModuleItem", type_hint: Union[type, str]
) -> Optional[Union[type, str]]:
# Primitives
if item.getType() == JByte:
return number_widget_for(jc.Byte)
if item.getType() == JShort:
return number_widget_for(jc.Short)
if item.getType() == JInt:
return number_widget_for(jc.Integer)
if item.getType() == JLong:
return number_widget_for(jc.Long)
if item.getType() == JFloat:
return number_widget_for(jc.Float)
if item.getType() == JDouble:
return number_widget_for(jc.Double)

# Boxed primitives
if issubclass(item.getType(), jc.Number):
return number_widget_for(item.getType())
return None


@_widget_preference
Expand Down
1 change: 1 addition & 0 deletions src/napari_imagej/widgets/napari_imagej.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ def wait_for_finalization(self):

@Slot(object)
def _handle_output(self, data):
print(f"handling {data}")
if isinstance(data, Layer):
self.napari_viewer.add_layer(data)
elif isinstance(data, dict):
Expand Down
33 changes: 24 additions & 9 deletions src/napari_imagej/widgets/parameter_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from typing import Any, Dict, List, Optional, TYPE_CHECKING

from imagej.images import _imglib2_types
from jpype import JArray, JClass, JInt, JLong
from jpype import JArray, JByte, JClass, JDouble, JFloat, JInt, JLong, JShort
from magicgui.types import ChoicesType
from magicgui.widgets import (
CheckBox,
Expand Down Expand Up @@ -104,7 +104,10 @@ def value(self):

@lru_cache(maxsize=None)
def number_widget_for(cls: type):
if not issubclass(cls, jc.Number):
if not (
cls in [JByte, JShort, JInt, JLong, JFloat, JDouble]
or issubclass(cls, jc.Number)
):
return None
# Sensible default for Number iface
if cls == jc.Number:
Expand All @@ -114,20 +117,32 @@ def number_widget_for(cls: type):
# We want the latter for use in numeric_bounds and in the widget subclass
if cls == jc.Byte:
cls = ctor = jc.Byte
if cls == jc.Short:
elif cls == jc.Short:
cls = ctor = jc.Short
if cls == jc.Integer:
elif cls == jc.Integer:
cls = ctor = jc.Integer
if cls == jc.Long:
elif cls == jc.Long:
cls = ctor = jc.Long
if cls == jc.Float:
elif cls == jc.Float:
cls = ctor = jc.Float
if cls == jc.Double:
elif cls == jc.Double:
cls = ctor = jc.Double
if cls == jc.BigInteger:
elif cls == JByte:
cls, ctor = jc.Byte, JByte
elif cls == JShort:
cls, ctor = jc.Short, JShort
elif cls == JInt:
cls, ctor = jc.Integer, JInt
elif cls == JLong:
cls, ctor = jc.Long, JLong
elif cls == JFloat:
cls, ctor = jc.Float, JFloat
elif cls == JDouble:
cls, ctor = jc.Double, JDouble
elif cls == jc.BigInteger:
cls = jc.BigInteger
ctor = jc.BigInteger.valueOf
if cls == jc.BigDecimal:
elif cls == jc.BigDecimal:
cls = jc.BigDecimal
ctor = jc.BigDecimal.valueOf

Expand Down
4 changes: 2 additions & 2 deletions tests/test_scripting.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ def DefaultModuleService(self):

def test_example_script_exists(ij):
"""
Asserts that Example_Script.js in the local scripts/examples directory can be found
Asserts that Example_Script.py in the local scripts/examples directory can be found
from the module service, AND that it can be converted into a magicgui widget.
"""
module_info = ij.module().getModuleById("script:examples/Example_Script.js")
module_info = ij.module().getModuleById("script:examples/Example_Script.py")
assert module_info is not None

module = ij.module().createModule(module_info)
Expand Down
29 changes: 18 additions & 11 deletions tests/widgets/test_parameter_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import importlib

from jpype import JByte, JDouble, JFloat, JInt, JLong, JShort
import napari
import numpy as np
import pytest
Expand Down Expand Up @@ -192,24 +193,30 @@ def test_mutable_output_add_new_image_dims_repeats(output_widget: MutableOutputW


def test_numbers(ij):
# NB See HACK for bounds number_widget_for
numbers = [
jc.Byte,
jc.Short,
jc.Integer,
jc.Long,
jc.Float,
jc.Double,
jc.BigInteger,
jc.BigDecimal,
(jc.Byte, jc.Byte),
(jc.Short, jc.Short),
(jc.Integer, jc.Integer),
(jc.Long, jc.Long),
(jc.Float, jc.Float),
(jc.Double, jc.Double),
(jc.BigInteger, jc.BigInteger),
(jc.BigDecimal, jc.BigDecimal),
(JByte, jc.Byte),
(JShort, jc.Short),
(JInt, jc.Integer),
(JLong, jc.Long),
(JFloat, jc.Float),
(JDouble, jc.Double),
]
for number in numbers:
# NB See HACK in number_widget_for
for number, bound_cls in numbers:
if number == jc.BigInteger:
min_val, max_val = numeric_bounds(jc.Long)
elif number == jc.BigDecimal:
min_val, max_val = numeric_bounds(jc.Double)
else:
min_val, max_val = numeric_bounds(number)
min_val, max_val = numeric_bounds(bound_cls)

widget = number_widget_for(number.class_)()
assert min_val == widget.min
Expand Down

0 comments on commit bb8e4f1

Please sign in to comment.