From nobody Tue May 13 13:08:59 2025 Delivered-To: importer2@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=patchew-devel-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=patchew-devel-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1557925117; cv=none; d=zoho.com; s=zohoarc; b=g0UDm4Bvlp4bKLYz1D7bjrhew7e6upqhY4+Qnucm1WVFSBMrWO2lJ683bfD4HjZP2BP4f1g6BLEfkf+d/JKXrWlU1l0FAQl7Kwow0tBP+vmFsxW4VbzxzxPwpHEVSF4Vk5GEOQtWw8FWxkbXCBsxtfRPu3NP7lMo0FvpgN+p/DM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1557925117; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=gu+SGAqMiiHXDgX5lkBElV4FhCj6nAeDH+Zo+K+6sas=; b=mjwgfm1dtR2zjnJi4PbdpaSMwDld4lwnJm2UIKEp+8PyWXT1qIDPHCo7U0gghs0T8bPPrS3uFu6PAaOn5w9FjkBkmLiwRKZFY5k55j1UV8OplmnlJc9UeJrZSsssT5jXFPuvWTBZ7ByippE+EMcSyiSW/4pPUnu60E1+Z64myCU= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=patchew-devel-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1557925117480548.5629757934771; Wed, 15 May 2019 05:58:37 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4C0083086208; Wed, 15 May 2019 12:58:36 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 415BA1001E61; Wed, 15 May 2019 12:58:36 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 3773C18089CB; Wed, 15 May 2019 12:58:36 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x4FCwYW3012663 for ; Wed, 15 May 2019 08:58:34 -0400 Received: by smtp.corp.redhat.com (Postfix) id C142760CC0; Wed, 15 May 2019 12:58:34 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-112-34.ams2.redhat.com [10.36.112.34]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6C6156114C for ; Wed, 15 May 2019 12:58:30 +0000 (UTC) From: Paolo Bonzini To: patchew-devel@redhat.com Date: Wed, 15 May 2019 14:58:01 +0200 Message-Id: <20190515125808.27716-5-pbonzini@redhat.com> In-Reply-To: <20190515125808.27716-1-pbonzini@redhat.com> References: <20190515125808.27716-1-pbonzini@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: patchew-devel@redhat.com Subject: [Patchew-devel] [PATCH 04/11] models: move here the code to add tags and generate a new mbox X-BeenThere: patchew-devel@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Patchew development and discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: quoted-printable Sender: patchew-devel-bounces@redhat.com Errors-To: patchew-devel-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Wed, 15 May 2019 12:58:36 +0000 (UTC) Content-Type: text/plain; charset="utf-8" This code will be reused by the REST API, move it under the Message class. Signed-off-by: Paolo Bonzini --- api/models.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++- www/views.py | 60 +++------------------------------------------------ 2 files changed, 62 insertions(+), 58 deletions(-) diff --git a/api/models.py b/api/models.py index 806a184..525be36 100644 --- a/api/models.py +++ b/api/models.py @@ -8,6 +8,8 @@ # This work is licensed under the MIT License. Please see the LICENSE fil= e or # http://opensource.org/licenses/MIT. import datetime +import email +import quopri import re =20 from django.core import validators @@ -17,7 +19,8 @@ from django.urls import reverse import jsonfield import lzma =20 -from mbox import MboxMessage +from mbox import MboxMessage, decode_payload +from patchew.tags import lines_iter from event import emit_event, declare_event from .blobs import save_blob, load_blob import mod @@ -542,6 +545,61 @@ class Message(models.Model): =20 mbox =3D property(get_mbox) =20 + def _get_mbox_with_tags(self, series_tags=3D[]): + def mbox_with_tags_iter(mbox, tags): + regex =3D "^[-A-Za-z]*:" + old_tags =3D set() + lines =3D lines_iter(mbox) + need_minusminusminus =3D False + for line in lines: + if line.startswith('---'): + need_minusminusminus =3D True + break + yield line + if re.match(regex, line): + old_tags.add(line) + + # If no --- line, tags go at the end as there's no better place + for tag in sorted(tags): + if tag not in old_tags: + yield tag + if need_minusminusminus: + yield line + yield from lines + + mbox =3D self.get_mbox() + msg =3D email.message_from_string(mbox) + container =3D msg.get_payload(0) if msg.is_multipart() else msg + if container.get_content_type() !=3D "text/plain": + return msg.as_bytes(unixfrom=3DTrue) + + payload =3D decode_payload(container) + # We might be adding 8-bit trailers to a message with 7bit CTE. F= or + # patches, quoted-printable is safe and mostly human-readable. + try: + container.replace_header('Content-Transfer-Encoding', 'quoted-= printable') + except KeyError: + msg.add_header('Content-Transfer-Encoding', 'quoted-printable') + payload =3D '\n'.join(mbox_with_tags_iter(payload, set(self.tags).= union(series_tags))) + payload =3D quopri.encodestring(payload.encode('utf-8')) + container.set_payload(payload, charset=3D'utf-8') + return msg.as_bytes(unixfrom=3DTrue) + + def get_mbox_with_tags(self): + if not self.is_patch: + if not self.is_complete: + return None + messages =3D self.get_patches() + series_tags =3D set(self.tags) + else: + messages =3D [self] + series_tags =3D set() + + mbox_list =3D [] + for message in messages: + mbox_list.append(message._get_mbox_with_tags(series_tags)) + return b"\n".join(mbox_list) + def get_num(self): assert self.is_patch or self.is_series_head cur, total =3D 1, 1 diff --git a/www/views.py b/www/views.py index f48a8ce..4436c7b 100644 --- a/www/views.py +++ b/www/views.py @@ -16,12 +16,8 @@ from django.urls import reverse from django.utils.html import format_html from django.conf import settings import api -import email -import quopri -from mbox import decode_payload import re from mod import dispatch_module_hook -from patchew.tags import lines_iter import subprocess =20 PAGE_SIZE =3D 50 @@ -264,62 +260,12 @@ def view_series_list(request, project): =20 =20 def view_mbox(request, project, message_id): - def mbox_with_tags_iter(mbox, tags): - regex =3D "^[-A-Za-z]*:" - old_tags =3D set() - lines =3D lines_iter(mbox) - need_minusminusminus =3D False - for line in lines: - if line.startswith('---'): - need_minusminusminus =3D True - break - yield line - if re.match(regex, line): - old_tags.add(line) - - # If no --- line, tags go at the end as there's no better place - for tag in sorted(tags): - if tag not in old_tags: - yield tag - if need_minusminusminus: - yield line - yield from lines - - def get_mbox_with_tags(m, series_tags): - mbox =3D m.get_mbox() - msg =3D email.message_from_string(mbox) - container =3D msg.get_payload(0) if msg.is_multipart() else msg - if container.get_content_type() !=3D "text/plain": - return msg.as_bytes(unixfrom=3DTrue) - - payload =3D decode_payload(container) - # We might be adding 8-bit trailers to a message with 7bit CTE. F= or - # patches, quoted-printable is safe and mostly human-readable. - try: - container.replace_header('Content-Transfer-Encoding', 'quoted-= printable') - except KeyError: - msg.add_header('Content-Transfer-Encoding', 'quoted-printable') - payload =3D '\n'.join(mbox_with_tags_iter(payload, set(m.tags).uni= on(series_tags))) - payload =3D quopri.encodestring(payload.encode('utf-8')) - container.set_payload(payload, charset=3D'utf-8') - return msg.as_bytes(unixfrom=3DTrue) - s =3D api.models.Message.objects.find_message(message_id, project) if not s: raise Http404("Series not found") - if not s.is_patch: - if not s.is_complete: - raise Http404("Series not complete") - messages =3D s.get_patches() - series_tags =3D set(s.tags) - else: - messages =3D [s] - series_tags =3D set() - - mbox_list =3D [] - for message in messages: - mbox_list.append(get_mbox_with_tags(message, series_tags)) - mbox =3D b"\n".join(mbox_list) + mbox =3D s.get_mbox_with_tags() + if not mbox: + raise Http404("Series not complete") return HttpResponse(mbox, content_type=3D"text/plain") =20 =20 --=20 2.21.0 _______________________________________________ Patchew-devel mailing list Patchew-devel@redhat.com https://www.redhat.com/mailman/listinfo/patchew-devel