[Patchew-devel] [PATCH 10/11] git: automatically derive the URL for result PUT

Paolo Bonzini pbonzini at redhat.com
Wed May 15 12:58:07 UTC 2019


Similar to commit 4efd0d21145a973f3321e9ec93700fb061b289f5 (git: allow not
passing the URL to applier-report) but for the REST API.
---
 api/rest.py       | 25 ++++++++++++++++++++++---
 mods/git.py       | 12 +++++++++++-
 mods/testing.py   |  3 ++-
 tests/test_git.py | 13 +++++++++++++
 4 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/api/rest.py b/api/rest.py
index c3ec3e1..e893e74 100644
--- a/api/rest.py
+++ b/api/rest.py
@@ -609,6 +609,16 @@ class HyperlinkedResultField(HyperlinkedIdentityField):
         return self.reverse(view_name, kwargs=kwargs, request=request, format=format)
 
 
+class ResultDataSerializer(serializers.Serializer):
+    def __init__(self, *args, **kwargs):
+        # Don't pass the 'project' arg up to the superclass
+        self.project = kwargs.pop('project', None)
+        super(ResultDataSerializer, self).__init__(*args, **kwargs)
+
+    def create(self, data):
+        return data
+
+
 class ResultSerializer(serializers.ModelSerializer):
     class Meta:
         model = Result
@@ -623,11 +633,19 @@ class ResultSerializer(serializers.ModelSerializer):
         request = self.context['request']
         return obj.get_log_url(request)
 
+    def get_data_serializer(self, *args, **kwargs):
+        project = self.context['parent'].project
+        data_serializer_class = self.context['renderer'].result_data_serializer_class
+        return data_serializer_class(*args, **kwargs, project=project, context=self.context)
+
+    def update(self, instance, validated_data):
+        if 'data' in validated_data:
+            validated_data['data'] = self.get_data_serializer().create(validated_data['data'])
+        return super(ResultSerializer, self).update(instance, validated_data)
+
     def validate(self, data):
         if 'data' in data:
-            data_serializer_class = self.context['renderer'].result_data_serializer_class
-            data_serializer_class(data=data['data'],
-                                  context=self.context).is_valid(raise_exception=True)
+            self.get_data_serializer(data=data['data']).is_valid(raise_exception=True)
         return data
 
 
@@ -671,6 +689,7 @@ class ResultsViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin,
         context = super(ResultsViewSet, self).get_serializer_context()
         if 'name' in self.kwargs:
             context['renderer'] = self.result_renderer
+        context['parent'] = self
         return context
 
     def get_serializer_class(self, *args, **kwargs):
diff --git a/mods/git.py b/mods/git.py
index 78939b8..b544b58 100644
--- a/mods/git.py
+++ b/mods/git.py
@@ -22,6 +22,7 @@ from django.db.models import Q
 from mod import PatchewModule
 from event import declare_event, register_handler, emit_event
 from api.models import (Message, Project, Result)
+import api.rest
 from api.rest import PluginMethodField, SeriesSerializer, reverse_detail
 from api.views import APILoginRequiredView, prepare_series
 from patchew.logviewer import LogView
@@ -47,7 +48,7 @@ class GitLogViewer(LogView):
             raise Http404("Object not found: " + series)
         return obj.git_result
 
-class ResultDataSerializer(serializers.Serializer):
+class ResultDataSerializer(api.rest.ResultDataSerializer):
     # TODO: should be present iff the result is success or failure
     base = CharField(required=False)
 
@@ -56,6 +57,15 @@ class ResultDataSerializer(serializers.Serializer):
     url = CharField(required=False)
     tag = CharField(required=False)
 
+    def create(self, data):
+        if 'tag' in data and 'url' not in data and self.project:
+            config = _instance.get_project_config(self.project)
+            url_template = config.get("url_template")
+            tag = data['tag']
+            if url_template and tag.startswith('refs/tags/'):
+                data['url'] = url_template.replace("%t", tag[10:])
+        return super(ResultDataSerializer, self).create(data)
+
 class GitModule(PatchewModule):
     """Git module"""
 
diff --git a/mods/testing.py b/mods/testing.py
index 1b914ce..16e652a 100644
--- a/mods/testing.py
+++ b/mods/testing.py
@@ -20,6 +20,7 @@ import time
 import math
 from api.views import APILoginRequiredView
 from api.models import (Message, MessageResult, Project, ProjectResult, Result)
+import api.rest
 from api.rest import PluginMethodField, TestPermission, reverse_detail
 from api.search import SearchEngine
 from event import emit_event, declare_event, register_handler
@@ -50,7 +51,7 @@ class TestingLogViewer(LogView):
             raise Http404("Object not found: " + project_or_series)
         return _instance.get_testing_result(obj, testing_name)
 
-class ResultDataSerializer(serializers.Serializer):
+class ResultDataSerializer(api.rest.ResultDataSerializer):
     # TODO: is_timeout should be present iff the result is a failure
     is_timeout = BooleanField(required=False)
     head = CharField()
diff --git a/tests/test_git.py b/tests/test_git.py
index e99755f..9b8de6d 100755
--- a/tests/test_git.py
+++ b/tests/test_git.py
@@ -144,6 +144,19 @@ class GitTest(PatchewTestCase):
         self.assertEqual(log.status_code, 200)
         self.assertEqual(log.content.decode(), resp.data['log'])
 
+    def test_result_data_automatic_url(self):
+        self.cli_import('0001-simple-patch.mbox.gz')
+        self.api_client.login(username=self.user, password=self.password)
+        resp = self.api_client.put(self.PROJECT_BASE + 'series/20160628014747.20971-1-famz at redhat.com/results/git/', {
+                'status': 'success',
+                'data': {
+                    'repo': self.repo,
+                    'tag': 'refs/tags/patchew/20160628014747.20971-1-famz at redhat.com'
+                }
+            }, format='json')
+        resp = self.api_client.get(self.PROJECT_BASE + 'series/20160628014747.20971-1-famz at redhat.com/results/git/')
+        self.assertIn('url', resp.data['data'])
+
     def test_rest_unapplied(self):
         self.cli_import('0004-multiple-patch-reviewed.mbox.gz')
         self.cli_import('0001-simple-patch.mbox.gz')
-- 
2.21.0





More information about the Patchew-devel mailing list