[Patchew-devel] [PATCH 04/12] models: move Result log_url from constructor to renderer

Fam Zheng famz at redhat.com
Tue May 22 08:00:37 UTC 2018


On Tue, 05/22 08:57, Paolo Bonzini wrote:
> The log_url is not going to be stored in the database.  In preparation for
> changing Result to a model, retrieve it through a method in the renderer.
> (The constructor and the renderer are actually always the same object
> currently :) but there will be no constructor concept will also disappear

s/there will be no/the/

> once Results will be fetched from the database).
> 
> This has other benefits too.  It also removes the request argument
> parameter from the Result constructor (which would not have any
> equivalent for database-stored Results) and from the rest_results_hook;
> and it makes log_url a read-only field in the REST API, which will be
> the right thing once PUT of Results will be supported.
> 
> Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
> ---
>  api/models.py   | 16 +++++++++++-----
>  api/rest.py     | 11 +++++++----
>  mods/git.py     | 15 ++++++++-------
>  mods/testing.py | 19 +++++++++++--------
>  www/views.py    |  4 ++--
>  5 files changed, 39 insertions(+), 26 deletions(-)
> 
> diff --git a/api/models.py b/api/models.py
> index 8f7ca19..0f25f85 100644
> --- a/api/models.py
> +++ b/api/models.py
> @@ -614,7 +614,7 @@ class Module(models.Model):
>      def __str__(self):
>          return self.name
>  
> -class Result(namedtuple("Result", "name status log log_url obj data renderer")):
> +class Result(namedtuple("Result", "name status log obj data renderer")):
>      __slots__ = ()
>      PENDING = 'pending'
>      SUCCESS = 'success'
> @@ -622,12 +622,10 @@ class Result(namedtuple("Result", "name status log log_url obj data renderer")):
>      RUNNING = 'running'
>      VALID_STATUSES = (PENDING, SUCCESS, FAILURE, RUNNING)
>  
> -    def __new__(cls, name, status, obj, log=None, log_url=None, data=None, request=None, renderer=None):
> -        if log_url is not None and request is not None:
> -            log_url = request.build_absolute_uri(log_url)
> +    def __new__(cls, name, status, obj, log=None, data=None, renderer=None):
>          if status not in cls.VALID_STATUSES:
>              raise ValueError("invalid value '%s' for status field" % status)
> -        return super(cls, Result).__new__(cls, status=status, log=log, log_url=log_url,
> +        return super(cls, Result).__new__(cls, status=status, log=log,
>                                            obj=obj, data=data, name=name, renderer=renderer)
>  
>      def is_success(self):
> @@ -649,3 +647,11 @@ class Result(namedtuple("Result", "name status log log_url obj data renderer")):
>          if self.renderer is None:
>              return None
>          return self.renderer.render_result(self)
> +
> +    def get_log_url(self, request=None):
> +        if not self.is_completed() or self.renderer is None:
> +            return None
> +        log_url = self.renderer.get_result_log_url(self.obj, self.name)
> +        if log_url is not None and request is not None:
> +            log_url = request.build_absolute_uri(log_url)
> +        return log_url
> diff --git a/api/rest.py b/api/rest.py
> index fa6ca3f..f36cf28 100644
> --- a/api/rest.py
> +++ b/api/rest.py
> @@ -19,7 +19,7 @@ from .search import SearchEngine
>  from rest_framework import (permissions, serializers, viewsets, filters,
>      mixins, generics, renderers, status)
>  from rest_framework.decorators import detail_route
> -from rest_framework.fields import SerializerMethodField, CharField, JSONField, EmailField
> +from rest_framework.fields import SerializerMethodField, CharField, JSONField, EmailField, SkipField

SkipField is unused?

Fam

>  from rest_framework.relations import HyperlinkedIdentityField
>  from rest_framework.response import Response
>  import rest_framework
> @@ -429,9 +429,13 @@ class ResultSerializer(serializers.Serializer):
>      resource_uri = HyperlinkedResultField(view_name='results-detail')
>      name = CharField()
>      status = CharField() # one of 'failure', 'success', 'pending', 'running'
> -    log_url = CharField(required=False)
> +    log_url = SerializerMethodField(required=False)
>      data = JSONField(required=False)
>  
> +    def get_log_url(self, obj):
> +        request = self.context['request']
> +        return obj.get_log_url(request)
> +
>  class ResultSerializerFull(ResultSerializer):
>      log = CharField(required=False)
>  
> @@ -452,8 +456,7 @@ class ResultsViewSet(viewsets.ViewSet, generics.GenericAPIView):
>          except IndexError:
>              raise Http404
>          results = []
> -        dispatch_module_hook("rest_results_hook", request=self.request,
> -                             obj=obj, results=results,
> +        dispatch_module_hook("rest_results_hook", obj=obj, results=results,
>                               detailed=detailed)
>          return {x.name: x for x in results}
>  
> diff --git a/mods/git.py b/mods/git.py
> index fe10423..a216ea2 100644
> --- a/mods/git.py
> +++ b/mods/git.py
> @@ -126,7 +126,7 @@ class GitModule(PatchewModule):
>      def rest_series_fields_hook(self, request, fields, detailed):
>          fields['based_on'] = PluginMethodField(obj=self, required=False)
>  
> -    def rest_results_hook(self, request, obj, results, detailed=False):
> +    def rest_results_hook(self, obj, results, detailed=False):
>          if not isinstance(obj, Message):
>              return
>          log = obj.get_property("git.apply-log")
> @@ -148,13 +148,10 @@ class GitModule(PatchewModule):
>                      if git_base:
>                          data['base'] = git_base
>                  status = Result.SUCCESS
> -            log_url = reverse("git-log", kwargs={'series': obj.message_id})
>          else:
>              status = Result.PENDING
> -            log_url = None
>          results.append(Result(name='git', obj=obj, status=status,
> -                              log=log, log_url=log_url, data=data,
> -                              request=request, renderer=self))
> +                              log=log, data=data, renderer=self))
>  
>      def prepare_message_hook(self, request, message, detailed):
>          if not message.is_series_head:
> @@ -199,9 +196,10 @@ class GitModule(PatchewModule):
>          if not result.is_completed():
>              return None
>  
> -        html_log_url = result.log_url + "?html=1"
> +        log_url = result.get_log_url()
> +        html_log_url = log_url + "?html=1"
>          colorbox_a = format_html('<a class="cbox-log" data-link="{}" href="{}">apply log</a>',
> -                                 html_log_url, result.log_url)
> +                                 html_log_url, log_url)
>          if result.is_failure():
>              return format_html('Failed in applying to current master ({})', colorbox_a)
>          else:
> @@ -218,6 +216,9 @@ class GitModule(PatchewModule):
>                  s += format_html('<br/><samp>git fetch {} {}</samp>', git_repo, git_tag)
>              return s
>  
> +    def get_result_log_url(eelf, obj, name):
> +        return reverse("git-log", kwargs={'series': obj.message_id})
> +
>      def prepare_project_hook(self, request, project):
>          if not project.maintained_by(request.user):
>              return
> diff --git a/mods/testing.py b/mods/testing.py
> index 824df15..2d379cb 100644
> --- a/mods/testing.py
> +++ b/mods/testing.py
> @@ -165,8 +165,8 @@ class TestingModule(PatchewModule):
>                                        "testing_name": test}) + "?type=project"
>          if html:
>              log_url += "&html=1"
> -        # Generate a full URL, including the host and port, for use in email
> -        # notifications and REST API responses.
> +        # Generate a full URL, including the host and port, for use in
> +        # email notifications
>          if request:
>              log_url = request.build_absolute_uri(log_url)
> @@ -251,7 +251,7 @@ class TestingModule(PatchewModule):
>                          })
>          return ret
>  
> -    def rest_results_hook(self, request, obj, results, detailed=False):
> +    def rest_results_hook(self, obj, results, detailed=False):
>          all_tests = set([k for k, v in _instance.get_tests(obj).items() if v["enabled"]])
>          for pn, p in obj.get_properties().items():
>              if not pn.startswith("testing.report."):
> @@ -262,7 +262,6 @@ class TestingModule(PatchewModule):
>              except:
>                  pass
>              failed = not p["passed"]
> -            log_url = self.reverse_testing_log(obj, tn, request=request, html=False)
>              passed_str = Result.FAILURE if failed else Result.SUCCESS
>              if detailed:
>                  log = obj.get_property("testing.log." + tn)
> @@ -272,8 +271,7 @@ class TestingModule(PatchewModule):
>              data = p.copy()
>              del data['passed']
>              results.append(Result(name='testing.' + tn, obj=obj, status=passed_str,
> -                                  log=log, log_url=log_url, request=request, data=data,
> -                                  renderer=self))
> +                                  log=log, data=data, renderer=self))
>  
>          if obj.get_property("testing.ready"):
>              for tn in all_tests:
> @@ -305,15 +303,20 @@ class TestingModule(PatchewModule):
>                  "char": "T",
>                  })
>  
> +    def get_result_log_url(self, obj, name):
> +        tn = name[len("testing."):]
> +        return self.reverse_testing_log(obj, tn, html=False)
> +
>      def render_result(self, result):
>          if not result.is_completed():
>              return None
>          pn = result.name
>          tn = pn[len("testing."):]
> -        html_log_url = result.log_url + '&html=1'
> +        log_url = result.get_log_url()
> +        html_log_url = log_url + '&html=1'
>          passed_str = "failed" if result.is_failure() else "passed"
>          return format_html('Test <b>{}</b> <a class="cbox-log" data-link="{}" href="{}">{}</a>',
> -                           tn, html_log_url, result.log_url, passed_str)
> +                           tn, html_log_url, log_url, passed_str)
>  
>      def check_active_testers(self, project):
>          at = []
> diff --git a/www/views.py b/www/views.py
> index 1eb6c3c..c2010c5 100644
> --- a/www/views.py
> +++ b/www/views.py
> @@ -93,8 +93,8 @@ def prepare_series(request, s, skip_patches=False):
>  
>  def prepare_results(request, obj):
>      results = []
> -    dispatch_module_hook("rest_results_hook", request=request,
> -                         obj=obj, results=results, detailed=False)
> +    dispatch_module_hook("rest_results_hook", obj=obj,
> +                         results=results, detailed=False)
>  
>      results_dicts = []
>      for result in results:
> -- 
> 2.17.0
> 
> 
> _______________________________________________
> Patchew-devel mailing list
> Patchew-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/patchew-devel




More information about the Patchew-devel mailing list