[RFC PATCH 1/4] patch-detail: add patch relation context

Raxel Gutierrez raxel at google.com
Tue Aug 24 00:58:44 AEST 2021


These changes are setup for the upcoming change that adds a patch
relations table to the submission page. In particular:

- Add unaddressed and addressed counts to patches and patch relations to
  be able to view the information in the patch relations table.
- Change the current patch tags count filter to a function of the patch
  object so that it can be used by the patch relations tags count filter.
- Add template filter that retrieves a summary of the existence of tags
  (e.g. A/R/T) for a given patch relation.
- Add the project maintainers as context to be auto-generate them in an
  email in the case that patch relations need to be modified.

Signed-off-by: Raxel Gutierrez <raxel at google.com>
---
 patchwork/models.py                           | 36 +++++++++++++++++++
 patchwork/templates/patchwork/submission.html |  4 +++
 patchwork/templatetags/patch.py               | 34 ++++++++++++------
 patchwork/views/patch.py                      | 23 +++++++++---
 4 files changed, 83 insertions(+), 14 deletions(-)

diff --git a/patchwork/models.py b/patchwork/models.py
index 58e4c51e..b1d8c5bc 100644
--- a/patchwork/models.py
+++ b/patchwork/models.py
@@ -462,6 +462,14 @@ class Patch(SubmissionMixin):
 
     objects = PatchManager()
 
+    @property
+    def unaddressed_comments_count(self):
+        return self.comments.filter(addressed=False).count()
+
+    @property
+    def addressed_comments_count(self):
+        return self.comments.filter(addressed=True).count()
+
     @staticmethod
     def extract_tags(content, tags):
         counts = Counter()
@@ -494,6 +502,18 @@ class Patch(SubmissionMixin):
         for tag in tags:
             self._set_tag(tag, counter[tag])
 
+    def patch_tags_count(self):
+        counts = []
+        titles = []
+        for tag in [t for t in self.project.tags if t.show_column]:
+            count = getattr(self, tag.attr_name)
+            titles.append('%d %s' % (count, tag.name))
+            if count == 0:
+                counts.append("-")
+            else:
+                counts.append(count)
+        return counts, titles
+
     def save(self, *args, **kwargs):
         if not hasattr(self, 'state') or not self.state:
             self.state = get_default_initial_patch_state()
@@ -950,6 +970,22 @@ class BundlePatch(models.Model):
 
 class PatchRelation(models.Model):
 
+    @property
+    def unaddressed_comments_total(self):
+        total = 0
+        patches = self.patches.all()
+        for patch in patches:
+            total += patch.unaddressed_comments_count
+        return total
+
+    @property
+    def addressed_comments_total(self):
+        total = 0
+        patches = self.patches.all()
+        for patch in patches:
+            total += patch.addressed_comments_count
+        return total
+
     def __str__(self):
         patches = self.patches.all()
         if not patches:
diff --git a/patchwork/templates/patchwork/submission.html b/patchwork/templates/patchwork/submission.html
index 2238e82e..7dd6ae97 100644
--- a/patchwork/templates/patchwork/submission.html
+++ b/patchwork/templates/patchwork/submission.html
@@ -9,6 +9,10 @@
 
 {% block headers %}
   <script type="module" src="{% static "js/submission.js" %}"></script>
+  <script type="text/javascript">
+    let is_editable = {{ editable|yesno:"true,false" }};
+    let django_maintainers_data = {{ maintainers|safe }}
+  </script>
 {% endblock %}
 
 {% block title %}{{submission.name}}{% endblock %}
diff --git a/patchwork/templatetags/patch.py b/patchwork/templatetags/patch.py
index 3837798d..c07c0bee 100644
--- a/patchwork/templatetags/patch.py
+++ b/patchwork/templatetags/patch.py
@@ -16,18 +16,25 @@ register = template.Library()
 
 @register.filter(name='patch_tags')
 def patch_tags(patch):
-    counts = []
-    titles = []
-    for tag in [t for t in patch.project.tags if t.show_column]:
-        count = getattr(patch, tag.attr_name)
-        titles.append('%d %s' % (count, tag.name))
-        if count == 0:
-            counts.append("-")
-        else:
-            counts.append(str(count))
+    counts, titles = patch.patch_tags_count()
     return mark_safe('<span title="%s">%s</span>' % (
         ' / '.join(titles),
-        ' '.join(counts)))
+        ' '.join([str(x) for x in counts])))
+
+
+ at register.filter(name='patch_relation_tags')
+def patch_relation_tags(related_patches, project):
+    tags = [tag.abbrev for tag in project.tags]
+    tags_summary = ["-" for _ in range(len(tags))]
+    for patch in related_patches:
+        counts = patch.patch_tags_count()[0]
+        for i, count in enumerate(counts):
+            if count != '-':
+                # Replaces a non-zero tag count with tag abbreviation
+                # to indicate that existence of such tag in the set
+                # of related patches
+                tags_summary[i] = tags[i]
+    return mark_safe('<span>%s</span>' % (' '.join(tags_summary)))
 
 
 @register.filter(name='patch_checks')
@@ -71,3 +78,10 @@ def patch_commit_display(patch):
 
     return mark_safe('<a href="%s">%s</a>' % (escape(fmt.format(commit)),
                                               escape(commit)))
+
+
+# TODO: can be modularized into a utils.py templatetags file
+# to get is_editable from any object
+ at register.filter(name='patch_is_editable')
+def patch_is_editable(patch, user):
+    return patch.is_editable(user)
diff --git a/patchwork/views/patch.py b/patchwork/views/patch.py
index 00b0147f..8e685add 100644
--- a/patchwork/views/patch.py
+++ b/patchwork/views/patch.py
@@ -40,7 +40,11 @@ def patch_detail(request, project_id, msgid):
 
     # redirect to cover letters where necessary
     try:
-        patch = Patch.objects.get(project_id=project.id, msgid=db_msgid)
+        # Current patch needs tag counts when no relation exists
+        patch_qs = Patch.objects.filter(
+            project_id=project.id, msgid=db_msgid
+        ).with_tag_counts(project)
+        patch = patch_qs.get()
     except Patch.DoesNotExist:
         covers = Cover.objects.filter(
             project_id=project.id,
@@ -113,15 +117,19 @@ def patch_detail(request, project_id, msgid):
                              'addressed')
 
     if patch.related:
-        related_same_project = patch.related.patches.only(
-            'name', 'msgid', 'project', 'related')
+        related_same_project = patch.related.patches.order_by('-id').only(
+            'name', 'msgid', 'project', 'related').with_tag_counts(project)
+        related_ids = {'ids': [rp.id for rp in related_same_project]}
         # avoid a second trip out to the db for info we already have
         related_different_project = [
             related_patch for related_patch in related_same_project
             if related_patch.project_id != patch.project_id
         ]
     else:
-        related_same_project = []
+        # If no patch relation exists, then current patch is only related.
+        # Add tag counts to the patch to display in patch relation table.
+        related_same_project = [patch]
+        related_ids = {'ids': [patch.id]}
         related_different_project = []
 
     context['comments'] = comments
@@ -133,7 +141,14 @@ def patch_detail(request, project_id, msgid):
     context['patchform'] = form
     context['createbundleform'] = createbundleform
     context['project'] = patch.project
+    context['maintainers'] = {
+        'maintainers': [
+            m.user.email for m in patch.project.maintainer_project.all()
+        ]
+    }
+    context['patch_relation'] = patch.related
     context['related_same_project'] = related_same_project
+    context['related_ids'] = related_ids
     context['related_different_project'] = related_different_project
 
     return render(request, 'patchwork/submission.html', context)
-- 
2.33.0.rc2.250.ged5fa647cd-goog



More information about the Patchwork mailing list