This is an automated email from the ASF dual-hosted git repository.

lahirujayathilake pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airavata-portals.git


The following commit(s) were added to refs/heads/main by this push:
     new 4bf6e6fe3 bug fix - properly save/update inputs/outputs of an 
application deployment
4bf6e6fe3 is described below

commit 4bf6e6fe31c9a670708d8df32d5d5127521cdc79
Author: lahiruj <[email protected]>
AuthorDate: Thu Jul 31 19:19:40 2025 -0400

    bug fix - properly save/update inputs/outputs of an application deployment
---
 .../django_airavata/apps/api/serializers.py        | 137 ++++++++++++++-------
 1 file changed, 92 insertions(+), 45 deletions(-)

diff --git a/airavata-django-portal/django_airavata/apps/api/serializers.py 
b/airavata-django-portal/django_airavata/apps/api/serializers.py
index c12f63dc5..63d14a499 100644
--- a/airavata-django-portal/django_airavata/apps/api/serializers.py
+++ b/airavata-django-portal/django_airavata/apps/api/serializers.py
@@ -4,6 +4,7 @@ import json
 import logging
 from pathlib import Path
 from urllib.parse import quote
+from airavata.model.application.io.ttypes import DataType
 
 from airavata.model.appcatalog.appdeployment.ttypes import (
     ApplicationDeploymentDescription,
@@ -312,59 +313,93 @@ class ApplicationModuleSerializer(
         return request.is_gateway_admin
 
 
-class InputDataObjectTypeSerializer(
-        thrift_utils.create_serializer_class(InputDataObjectType)):
-    metaData = StoredJSONField(required=False, allow_null=True)
+class EnumChoiceField(serializers.ChoiceField):
+    def __init__(self, enum_class, **kwargs):
+        self.enum_class = enum_class
+        kwargs['choices'] = [(member.name, member.name) for member in 
enum_class]
+        super().__init__(**kwargs)
 
-    class Meta:
-        required = ('name',)
+    def to_internal_value(self, data):
+        if isinstance(data, int):
+            try:
+                return self.enum_class(data)
+            except ValueError:
+                self.fail('invalid_choice', input=data)
+        try:
+            return self.enum_class[data]
+        except KeyError:
+            self.fail('invalid_choice', input=data)
 
+    def to_representation(self, value):
+        return value.name
 
-class OutputDataObjectTypeSerializer(
-        thrift_utils.create_serializer_class(OutputDataObjectType)):
-    metaData = StoredJSONField(required=False, allow_null=True)
 
-    class Meta:
-        required = ('name',)
+class InputDataObjectTypeSerializer(serializers.Serializer):
+    name = serializers.CharField()
+    value = serializers.CharField(allow_blank=True, allow_null=True, 
required=False)
+    type = EnumChoiceField(enum_class=DataType)
+    applicationArgument = serializers.CharField(allow_blank=True, 
allow_null=True, required=False)
+    standardInput = serializers.BooleanField(default=False)
+    userFriendlyDescription = serializers.CharField(allow_blank=True, 
allow_null=True, required=False)
+    metaData = serializers.CharField(allow_blank=True, allow_null=True, 
required=False)
+    inputOrder = serializers.IntegerField(required=False, allow_null=True)
+    isRequired = serializers.BooleanField(default=False)
+    requiredToAddedToCommandLine = serializers.BooleanField(default=False)
+    dataStaged = serializers.BooleanField(default=False)
+    storageResourceId = serializers.CharField(allow_blank=True, 
allow_null=True, required=False)
+    isReadOnly = serializers.BooleanField(default=False)
+    overrideFilename = serializers.CharField(allow_blank=True, 
allow_null=True, required=False)
 
+    def create(self, validated_data):
+        return InputDataObjectType(**validated_data)
+
+    def update(self, instance, validated_data):
+        for attr, value in validated_data.items():
+            setattr(instance, attr, value)
+        return instance
+
+class OutputDataObjectTypeSerializer(serializers.Serializer):
+    name = serializers.CharField()
+    value = serializers.CharField(allow_blank=True, allow_null=True, 
required=False)
+    type = EnumChoiceField(enum_class=DataType)
+    applicationArgument = serializers.CharField(allow_blank=True, 
allow_null=True, required=False)
+    isRequired = serializers.BooleanField(default=False)
+    requiredToAddedToCommandLine = serializers.BooleanField(default=False)
+    dataMovement = serializers.BooleanField(default=False)
+    location = serializers.CharField(allow_blank=True, allow_null=True, 
required=False)
+    searchQuery = serializers.CharField(allow_blank=True, allow_null=True, 
required=False)
+    outputStreaming = serializers.BooleanField(default=False)
+    storageResourceId = serializers.CharField(allow_blank=True, 
allow_null=True, required=False)
+    metaData = serializers.CharField(allow_blank=True, allow_null=True, 
required=False)
+
+    def create(self, validated_data):
+        return OutputDataObjectType(**validated_data)
+
+    def update(self, instance, validated_data):
+        for attr, value in validated_data.items():
+            setattr(instance, attr, value)
+        return instance
+
+class ApplicationInterfaceDescriptionSerializer(serializers.Serializer):
+    applicationInterfaceId = serializers.CharField(required=False)
+    applicationName = serializers.CharField()
+    applicationDescription = serializers.CharField(allow_blank=True, 
allow_null=True, required=False)
+    applicationModules = serializers.ListField(child=serializers.CharField(), 
allow_null=True, required=False)
+    applicationInputs = InputDataObjectTypeSerializer(many=True, 
allow_null=True, required=False)
+    applicationOutputs = OutputDataObjectTypeSerializer(many=True, 
allow_null=True, required=False)
+    archiveWorkingDirectory = serializers.BooleanField(default=False)
+    hasOptionalFileInputs = serializers.BooleanField(default=False, 
read_only=True)
 
-class ApplicationInterfaceDescriptionSerializer(
-        thrift_utils.create_serializer_class(ApplicationInterfaceDescription)):
     url = FullyEncodedHyperlinkedIdentityField(
         view_name='django_airavata_api:application-interface-detail',
         lookup_field='applicationInterfaceId',
-        lookup_url_kwarg='app_interface_id')
-    applicationInputs = OrderedListField(
-        order_by='inputOrder',
-        child=InputDataObjectTypeSerializer(),
-        allow_null=True)
-    applicationOutputs = OutputDataObjectTypeSerializer(many=True)
+        lookup_url_kwarg='app_interface_id', read_only=True)
     userHasWriteAccess = serializers.SerializerMethodField()
     showQueueSettings = serializers.BooleanField(required=False)
     queueSettingsCalculatorId = serializers.CharField(allow_null=True, 
required=False)
 
-    def to_representation(self, instance):
-        representation = super().to_representation(instance)
-        application_module_id = instance.applicationModules[0]
-        application_settings, created = 
models.ApplicationSettings.objects.get_or_create(
-            application_module_id=application_module_id)
-        representation["showQueueSettings"] = 
application_settings.show_queue_settings
-        # check that queue_settings_calculator_id exists
-        if 
queue_settings_calculators.exists(application_settings.queue_settings_calculator_id):
-            representation["queueSettingsCalculatorId"] = 
application_settings.queue_settings_calculator_id
-        return representation
-
     def create(self, validated_data):
-        showQueueSettings = validated_data.pop("showQueueSettings", True)
-        queueSettingsCalculatorId = 
validated_data.pop("queueSettingsCalculatorId", None)
-        application_interface = super().create(validated_data)
-        application_module_id = application_interface.applicationModules[0]
-        models.ApplicationSettings.objects.update_or_create(
-            application_module_id=application_module_id,
-            defaults={"show_queue_settings": showQueueSettings,
-                      "queue_settings_calculator_id": 
queueSettingsCalculatorId}
-        )
-        return application_interface
+        return ApplicationInterfaceDescription(**validated_data)
 
     def update(self, instance, validated_data):
         defaults = {}
@@ -372,12 +407,24 @@ class ApplicationInterfaceDescriptionSerializer(
             defaults["show_queue_settings"] = 
validated_data.pop("showQueueSettings")
         if "queueSettingsCalculatorId" in validated_data:
             defaults["queue_settings_calculator_id"] = 
validated_data.pop("queueSettingsCalculatorId")
-        application_interface = super().update(instance, validated_data)
-        application_module_id = application_interface.applicationModules[0]
-        models.ApplicationSettings.objects.update_or_create(
-            application_module_id=application_module_id, defaults=defaults
-        )
-        return application_interface
+        application_module_id = instance.applicationModules[0]
+        if defaults:
+            models.ApplicationSettings.objects.update_or_create(
+                application_module_id=application_module_id, defaults=defaults
+            )
+
+        inputs_data = validated_data.pop('applicationInputs', None)
+        outputs_data = validated_data.pop('applicationOutputs', None)
+
+        for attr, value in validated_data.items():
+            setattr(instance, attr, value)
+
+        if inputs_data is not None:
+            instance.applicationInputs = [InputDataObjectType(**inp) for inp 
in inputs_data]
+        if outputs_data is not None:
+            instance.applicationOutputs = [OutputDataObjectType(**out) for out 
in outputs_data]
+
+        return instance
 
     def get_userHasWriteAccess(self, appDeployment):
         request = self.context['request']

Reply via email to