Skip to content

Commit

Permalink
Require default interface for algorithm (#3759)
Browse files Browse the repository at this point in the history
Adds a check to both the form and the model that ensures that an
algorithm has a default interface. We're not using the through model
directly to create an interface for an algorithm through the UI, hence
the check in 2 places.
  • Loading branch information
amickan authored Dec 18, 2024
1 parent 5990745 commit 6e2da3d
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 1 deletion.
8 changes: 8 additions & 0 deletions app/grandchallenge/algorithms/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,14 @@ def __init__(self, *args, algorithm, **kwargs):
if not self._algorithm.default_interface:
self.fields["set_as_default"].initial = True

def clean_set_as_default(self):
set_as_default = self.cleaned_data["set_as_default"]

if not set_as_default and not self._algorithm.default_interface:
raise ValidationError("Your algorithm needs a default interface.")

return set_as_default

def clean(self):
cleaned_data = super().clean()

Expand Down
6 changes: 6 additions & 0 deletions app/grandchallenge/algorithms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,12 @@ class Meta:
def __str__(self):
return str(self.interface)

def clean(self):
super().clean()

if not self.is_default and not self.algorithm.default_interface:
raise ValidationError("This algorithm needs a default interface.")


class AlgorithmUserObjectPermission(UserObjectPermissionBase):
content_object = models.ForeignKey(Algorithm, on_delete=models.CASCADE)
Expand Down
26 changes: 25 additions & 1 deletion app/tests/algorithms_tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -1364,6 +1364,30 @@ def test_algorithm_interface_disjoint_interfaces():
assert "The sets of Inputs and Outputs must be unique" in str(form.errors)


@pytest.mark.django_db
def test_algorithm_interface_default_interface_required():
ci1, ci2 = ComponentInterfaceFactory.create_batch(2)
alg = AlgorithmFactory()
form = AlgorithmInterfaceForm(
algorithm=alg,
data={"inputs": [ci1], "outputs": [ci2], "set_as_default": False},
)
assert form.is_valid() is False
assert "Your algorithm needs a default interface" in str(
form.errors["set_as_default"]
)

alg.interfaces.add(
AlgorithmInterfaceFactory(), through_defaults={"is_default": True}
)
del alg.default_interface
form = AlgorithmInterfaceForm(
algorithm=alg,
data={"inputs": [ci1], "outputs": [ci2], "set_as_default": False},
)
assert form.is_valid()


def test_algorithm_for_phase_form_memory():
form = AlgorithmForPhaseForm(
workstation_config=WorkstationConfigFactory.build(),
Expand Down Expand Up @@ -1427,7 +1451,7 @@ def test_existing_io_is_reused(self):
data={
"inputs": [inp.pk],
"outputs": [out.pk],
"set_as_default": False,
"set_as_default": True,
},
)
assert form.is_valid()
Expand Down

0 comments on commit 6e2da3d

Please sign in to comment.