This is an automated email from the ASF dual-hosted git repository.
yasithdev 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 46d6e11dc refactor(portal): make ApplicationModuleSerializer
proto-native (Track D) (#194)
46d6e11dc is described below
commit 46d6e11dc43701f9dbdb4971724879c7ffc31575
Author: Yasith Jayawardana <[email protected]>
AuthorDate: Tue Jun 9 03:31:47 2026 -0400
refactor(portal): make ApplicationModuleSerializer proto-native (Track D)
(#194)
Rewrite ApplicationModuleSerializer to read the gRPC ApplicationModule
protobuf
directly and emit the same Thrift-named JSON keys, keeping the REST contract
byte-for-byte unchanged.
- save() returns a proto ApplicationModule the view passes straight to the
facade.
- Repoint ApplicationModuleViewSet
(list/instance/create/update/destroy/list_all)
and FullExperimentViewSet's nested module to pass protobuf through
directly,
dropping the grpc_adapters.application_module /
grpc_requests.application_module
roundtrip.
- Remove those adapter funcs + the Thrift ApplicationModule import.
Validated byte-for-byte (full/empty) vs the old adapter+serializer path;
write
path (create/update) produces an equivalent proto. manage.py check green;
api
test failures unchanged vs origin/main.
---
.../django_airavata/apps/api/grpc_adapters.py | 10 -----
.../django_airavata/apps/api/grpc_requests.py | 10 -----
.../django_airavata/apps/api/serializers.py | 49 ++++++++++++++++++----
.../django_airavata/apps/api/views.py | 28 +++++--------
4 files changed, 51 insertions(+), 46 deletions(-)
diff --git a/airavata-django-portal/django_airavata/apps/api/grpc_adapters.py
b/airavata-django-portal/django_airavata/apps/api/grpc_adapters.py
index 0c54f8570..72bede0c8 100644
--- a/airavata-django-portal/django_airavata/apps/api/grpc_adapters.py
+++ b/airavata-django-portal/django_airavata/apps/api/grpc_adapters.py
@@ -256,16 +256,6 @@ def proto_summary_type(thrift_summary_type):
_ThriftSummaryType(thrift_summary_type).name)
-def application_module(pb):
- """gRPC ``ApplicationModule`` protobuf -> ``ApplicationModuleSerializer``
shape."""
- return SimpleNamespace(
- appModuleId=pb.app_module_id,
- appModuleName=pb.app_module_name,
- appModuleVersion=pb.app_module_version,
- appModuleDescription=pb.app_module_description,
- )
-
-
def experiment_summary(pb):
"""gRPC ``ExperimentSummaryModel`` protobuf ->
``ExperimentSummarySerializer`` shape."""
return SimpleNamespace(
diff --git a/airavata-django-portal/django_airavata/apps/api/grpc_requests.py
b/airavata-django-portal/django_airavata/apps/api/grpc_requests.py
index 292ed88b3..f596dd65e 100644
--- a/airavata-django-portal/django_airavata/apps/api/grpc_requests.py
+++ b/airavata-django-portal/django_airavata/apps/api/grpc_requests.py
@@ -80,16 +80,6 @@ def password_credential(gateway_id, portal_user_name,
login_user_name,
)
-def application_module(t):
- """Thrift ``ApplicationModule`` -> proto ``ApplicationModule``."""
- return
_pb2("appcatalog.appdeployment.app_deployment_pb2").ApplicationModule(
- app_module_id=t.appModuleId or '',
- app_module_name=t.appModuleName or '',
- app_module_version=t.appModuleVersion or '',
- app_module_description=t.appModuleDescription or '',
- )
-
-
def _input_data_object(t):
io = _pb2("application.io.application_io_pb2")
return io.InputDataObjectType(
diff --git a/airavata-django-portal/django_airavata/apps/api/serializers.py
b/airavata-django-portal/django_airavata/apps/api/serializers.py
index ddc270c00..14b6cd3a8 100644
--- a/airavata-django-portal/django_airavata/apps/api/serializers.py
+++ b/airavata-django-portal/django_airavata/apps/api/serializers.py
@@ -9,7 +9,6 @@ from airavata.model.application.io.ttypes import DataType
from airavata.model.appcatalog.appdeployment.ttypes import (
ApplicationDeploymentDescription,
- ApplicationModule,
CommandObject,
SetEnvPaths
)
@@ -355,26 +354,58 @@ class ProjectSerializer(serializers.Serializer):
return project.owner == request.user.username
-class ApplicationModuleSerializer(
- thrift_utils.create_serializer_class(ApplicationModule)):
+class ApplicationModuleSerializer(serializers.Serializer):
+ """Proto-native serializer for the gRPC ``ApplicationModule`` message.
+
+ Reads the protobuf directly and emits the historical Thrift-named JSON
keys.
+ ``save()`` returns a proto ``ApplicationModule`` the view passes to the
facade.
+ """
+
+ appModuleId = serializers.CharField(source='app_module_id', read_only=True)
+ appModuleName = serializers.CharField(source='app_module_name')
+ appModuleVersion = serializers.CharField(
+ source='app_module_version', allow_blank=True, allow_null=True,
+ required=False)
+ appModuleDescription = serializers.CharField(
+ source='app_module_description', allow_blank=True, allow_null=True,
+ required=False)
url = FullyEncodedHyperlinkedIdentityField(
view_name='django_airavata_api:application-detail',
- lookup_field='appModuleId',
+ lookup_field='app_module_id',
lookup_url_kwarg='app_module_id')
applicationInterface = FullyEncodedHyperlinkedIdentityField(
view_name='django_airavata_api:application-application-interface',
- lookup_field='appModuleId',
+ lookup_field='app_module_id',
lookup_url_kwarg='app_module_id')
applicationDeployments = FullyEncodedHyperlinkedIdentityField(
view_name='django_airavata_api:application-application-deployments',
- lookup_field='appModuleId',
+ lookup_field='app_module_id',
lookup_url_kwarg='app_module_id')
userHasWriteAccess = serializers.SerializerMethodField()
- class Meta:
- required = ('appModuleName',)
+ def create(self, validated_data):
+ from
airavata_sdk.generated.org.apache.airavata.model.appcatalog.appdeployment
import ( # noqa: E501
+ app_deployment_pb2,
+ )
+ return app_deployment_pb2.ApplicationModule(
+ app_module_name=validated_data.get('app_module_name', '') or '',
+ app_module_version=validated_data.get('app_module_version', '') or
'',
+ app_module_description=validated_data.get(
+ 'app_module_description', '') or '',
+ )
- def get_userHasWriteAccess(self, appDeployment):
+ def update(self, instance, validated_data):
+ if 'app_module_name' in validated_data:
+ instance.app_module_name = validated_data['app_module_name'] or ''
+ if 'app_module_version' in validated_data:
+ instance.app_module_version = (
+ validated_data['app_module_version'] or '')
+ if 'app_module_description' in validated_data:
+ instance.app_module_description = (
+ validated_data['app_module_description'] or '')
+ return instance
+
+ def get_userHasWriteAccess(self, appModule):
request = self.context['request']
return request.is_gateway_admin
diff --git a/airavata-django-portal/django_airavata/apps/api/views.py
b/airavata-django-portal/django_airavata/apps/api/views.py
index 5df6fc950..b59337bd4 100644
--- a/airavata-django-portal/django_airavata/apps/api/views.py
+++ b/airavata-django-portal/django_airavata/apps/api/views.py
@@ -434,7 +434,7 @@ class FullExperimentViewSet(mixins.RetrieveModelMixin,
try:
if applicationInterface is not None:
appModuleId = applicationInterface.applicationModules[0]
- applicationModule = grpc_adapters.application_module(
+ applicationModule = (
self.request.airavata.research.get_application_module(
appModuleId))
else:
@@ -484,30 +484,27 @@ class ApplicationModuleViewSet(APIBackedViewSet):
lookup_field = 'app_module_id'
def get_list(self):
- return [
- grpc_adapters.application_module(m)
- for m in self.request.airavata.research.get_accessible_app_modules(
- gateway_id=self.gateway_id)
- ]
+ return list(self.request.airavata.research.get_accessible_app_modules(
+ gateway_id=self.gateway_id))
def get_instance(self, lookup_value):
- return grpc_adapters.application_module(
-
self.request.airavata.research.get_application_module(lookup_value))
+ return self.request.airavata.research.get_application_module(
+ lookup_value)
def perform_create(self, serializer):
app_module = serializer.save()
app_module_id =
self.request.airavata.research.register_application_module(
- self.gateway_id, grpc_requests.application_module(app_module))
- app_module.appModuleId = app_module_id
+ self.gateway_id, app_module)
+ app_module.app_module_id = app_module_id
def perform_update(self, serializer):
app_module = serializer.save()
self.request.airavata.research.update_application_module(
- app_module.appModuleId,
grpc_requests.application_module(app_module))
+ app_module.app_module_id, app_module)
def perform_destroy(self, instance):
self.request.airavata.research.delete_application_module(
- instance.appModuleId)
+ instance.app_module_id)
@action(detail=True)
def application_interface(self, request, app_module_id):
@@ -587,11 +584,8 @@ class ApplicationModuleViewSet(APIBackedViewSet):
@action(detail=False)
def list_all(self, request, format=None):
- all_modules = [
- grpc_adapters.application_module(m)
- for m in self.request.airavata.research.get_all_app_modules(
- gateway_id=self.gateway_id)
- ]
+ all_modules = list(self.request.airavata.research.get_all_app_modules(
+ gateway_id=self.gateway_id))
serializer = self.serializer_class(
all_modules, many=True, context={'request': request})
return Response(serializer.data)