From nobody Thu May 2 15:14:31 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 206.53.239.180 is neither permitted nor denied by domain of freelists.org) client-ip=206.53.239.180; envelope-from=patchew-devel-bounce@freelists.org; helo=turing.freelists.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=none (zoho.com: 206.53.239.180 is neither permitted nor denied by domain of freelists.org) smtp.mailfrom=patchew-devel-bounce@freelists.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from turing.freelists.org (turing.freelists.org [206.53.239.180]) by mx.zohomail.com with SMTPS id 1520241398259342.26449464871473; Mon, 5 Mar 2018 01:16:38 -0800 (PST) Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id A948B270A3; Mon, 5 Mar 2018 04:16:37 -0500 (EST) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id KPlU337L5FGw; Mon, 5 Mar 2018 04:16:37 -0500 (EST) Received: from turing.freelists.org (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 5E66826402; Mon, 5 Mar 2018 04:16:37 -0500 (EST) Received: with ECARTIS (v1.0.0; list patchew-devel); Mon, 05 Mar 2018 04:16:37 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 2ACC7270A3 for ; Mon, 5 Mar 2018 04:16:37 -0500 (EST) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id cMwuYEw4xoBK for ; Mon, 5 Mar 2018 04:16:37 -0500 (EST) Received: from mail-wm0-f65.google.com (mail-wm0-f65.google.com [74.125.82.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id D316E26402 for ; Mon, 5 Mar 2018 04:16:36 -0500 (EST) Received: by mail-wm0-f65.google.com with SMTP id h21so14292126wmd.1 for ; Mon, 05 Mar 2018 01:16:36 -0800 (PST) Received: from donizetti.lan (94-36-191-219.adsl-ull.clienti.tiscali.it. [94.36.191.219]) by smtp.gmail.com with ESMTPSA id b68sm7018546wmi.30.2018.03.05.01.16.34 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 05 Mar 2018 01:16:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=freelists.org; s=turing; t=1520241397; bh=scZfPb47dNWuJSM/6SslEaJ9tCLnN29c54XFLt055KA=; h=From:To:Subject:Date:In-Reply-To:References:Reply-To:List-help: List-unsubscribe:List-Id:List-subscribe:List-owner:List-post: List-archive; b=YWCpGk6aGeGRnoNcHCj8KKNfjYTEeNYzm3uyCDfwDMHHxsjien4q4xEZW3HHsA5Xx sTwZ3LCeAy66oVhNrI9+IpOrz/noX3ga4a6lt2nQgr1vffPMmk0V+2PvySSjreSUew Mc6V/mPq8fR1AaR+rknaCFuyDeSPzJk0kZtRwRMI= X-Virus-Scanned: Debian amavisd-new at turing.freelists.org DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=freelists.org; s=turing; t=1520241397; bh=scZfPb47dNWuJSM/6SslEaJ9tCLnN29c54XFLt055KA=; h=From:To:Subject:Date:In-Reply-To:References:Reply-To:List-help: List-unsubscribe:List-Id:List-subscribe:List-owner:List-post: List-archive; b=YWCpGk6aGeGRnoNcHCj8KKNfjYTEeNYzm3uyCDfwDMHHxsjien4q4xEZW3HHsA5Xx sTwZ3LCeAy66oVhNrI9+IpOrz/noX3ga4a6lt2nQgr1vffPMmk0V+2PvySSjreSUew Mc6V/mPq8fR1AaR+rknaCFuyDeSPzJk0kZtRwRMI= X-Original-To: patchew-devel@freelists.org X-Virus-Scanned: Debian amavisd-new at turing.freelists.org X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:subject:date:message-id :in-reply-to:references; bh=N0GVbxiXNH+ISThVMNHH1tYVNVLHqNULUdIk7uOb6ek=; b=jISDlnifq5xXQkWqQ+tHilFramT0NHYB0K3FVtMncl+eHfR0Wy1NxNUkn1OeW2/9oh BdHg62gFfb5gmFiUMwMpqhaRrhcjdvUCNuwHvp2ROfjQpIQMtqF3YBMhAOKqyKmfLIZD +4iVl5pujeJ6EVHPM+2F0pYL+NCwNPtKrSb3RarWQsdmjCUEDzcLJA1YH/WIUE8j/pTM 2cD7d1D9RtYJf89CDbllx9B0I+kPjeebH42Ypx4PHBsITXlNBH6i3pZrGmOJPuyyKLMV adVMmCZvo7HVzGsH4Z1k2MZU085kUuqvXRKLtoAFNUroXNUPLTZmragCZsNMCg4HxFRD 6EYw== X-Gm-Message-State: AElRT7F8oNEszusM2B3bs8Zd7I4iN7cvYbbcjUODkFj5MgtiVpU0ZsCG 81UY+q2JzuSFp1721wHB9cN3pgAZ X-Google-Smtp-Source: AG47ELv854jajZIaxmmdNzM7Z/I4oYUyjZPwSq9absig9EVN4PxueZLKM/vZNk4o7CRrMCG1OW64rA== X-Received: by 10.28.35.14 with SMTP id j14mr6877755wmj.43.1520241394983; Mon, 05 Mar 2018 01:16:34 -0800 (PST) From: Paolo Bonzini To: patchew-devel@freelists.org Subject: [patchew-devel] [PATCH 1/6] ansi2html: add _write_form_feed Date: Mon, 5 Mar 2018 10:16:29 +0100 Message-Id: <20180305091634.7391-2-pbonzini@redhat.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180305091634.7391-1-pbonzini@redhat.com> References: <20180305091634.7391-1-pbonzini@redhat.com> X-archive-position: 73 X-ecartis-version: Ecartis v1.0.0 Sender: patchew-devel-bounce@freelists.org Errors-to: patchew-devel-bounce@freelists.org X-original-sender: pbonzini@redhat.com Precedence: normal Reply-To: patchew-devel@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: patchew-devel X-List-ID: patchew-devel List-subscribe: List-owner: List-post: List-archive: X-list: patchew-devel X-ZohoMail-DKIM: pass (identity @freelists.org) X-ZohoMail: RDKM_0 RSF_4 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Form feeds are rendered differently by HTML and text converters, so move the HTML rendering out of _write_line's argument. Signed-off-by: Paolo Bonzini --- patchew/logviewer.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/patchew/logviewer.py b/patchew/logviewer.py index bf67149..ab5f5c3 100644 --- a/patchew/logviewer.py +++ b/patchew/logviewer.py @@ -197,6 +197,9 @@ class ANSI2HTMLConverter(object): # the remaining light colors: dark grey and white self.bg =3D arg - 92 =20 + def _write_form_feed(self): + yield '
' + def _class_to_id(self, html_class): class_id =3D self.class_to_id.get(html_class, None) if class_id is None: @@ -319,7 +322,8 @@ class ANSI2HTMLConverter(object): =20 if csi[-1] =3D=3D 'J': save_pos =3D self.pos - yield from self._write_line('
') + yield from self._write_line('') + yield from self._write_form_feed() self._set_pos(save_pos) elif csi[-1] =3D=3D 'K': self._parse_csi_with_args(csi, self._do_csi_K) @@ -346,7 +350,8 @@ class ANSI2HTMLConverter(object): yield from self._write_line('\n') continue elif seq =3D=3D '\f': - yield from self._write_line('\n
') + yield from self._write_line('\n') + yield from self._write_form_feed() continue =20 if self.lazy_contents !=3D '': --=20 2.14.3 From nobody Thu May 2 15:14:31 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 206.53.239.180 is neither permitted nor denied by domain of freelists.org) client-ip=206.53.239.180; envelope-from=patchew-devel-bounce@freelists.org; helo=turing.freelists.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=none (zoho.com: 206.53.239.180 is neither permitted nor denied by domain of freelists.org) smtp.mailfrom=patchew-devel-bounce@freelists.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from turing.freelists.org (turing.freelists.org [206.53.239.180]) by mx.zohomail.com with SMTPS id 1520241399408856.2347554448638; Mon, 5 Mar 2018 01:16:39 -0800 (PST) Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id D7DC82716E; Mon, 5 Mar 2018 04:16:38 -0500 (EST) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1A0DShvLCUCM; Mon, 5 Mar 2018 04:16:38 -0500 (EST) Received: from turing.freelists.org (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 875C426402; Mon, 5 Mar 2018 04:16:38 -0500 (EST) Received: with ECARTIS (v1.0.0; list patchew-devel); Mon, 05 Mar 2018 04:16:38 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 5082C2716E for ; Mon, 5 Mar 2018 04:16:38 -0500 (EST) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id QGv_gdECHEHf for ; Mon, 5 Mar 2018 04:16:38 -0500 (EST) Received: from mail-wm0-f68.google.com (mail-wm0-f68.google.com [74.125.82.68]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id DF59E26402 for ; Mon, 5 Mar 2018 04:16:37 -0500 (EST) Received: by mail-wm0-f68.google.com with SMTP id i3so13916067wmi.4 for ; Mon, 05 Mar 2018 01:16:37 -0800 (PST) Received: from donizetti.lan (94-36-191-219.adsl-ull.clienti.tiscali.it. [94.36.191.219]) by smtp.gmail.com with ESMTPSA id b68sm7018546wmi.30.2018.03.05.01.16.35 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 05 Mar 2018 01:16:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=freelists.org; s=turing; t=1520241398; bh=wlgGELUmas3VJ94E0TRg57wSeg/G/1Hbs0zEEi1fMQw=; h=From:To:Subject:Date:In-Reply-To:References:Reply-To:List-help: List-unsubscribe:List-Id:List-subscribe:List-owner:List-post: List-archive; b=D866JLpn8EKuiGRwUA6OWcnpxipd7zS7uaMp73utOakr2/906QBRkxPaY1o5C29KK vdZZ8fwbJT1VvzFgwoPITkKjQ+yEp9LjYnU1xhbkcxNbXHjCbDqK4Vt52f9oPiPMfn NdWQdcDqLDq7zqN/41Gb9Zgc8OrHiruuZl3fnirs= X-Virus-Scanned: Debian amavisd-new at turing.freelists.org DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=freelists.org; s=turing; t=1520241398; bh=wlgGELUmas3VJ94E0TRg57wSeg/G/1Hbs0zEEi1fMQw=; h=From:To:Subject:Date:In-Reply-To:References:Reply-To:List-help: List-unsubscribe:List-Id:List-subscribe:List-owner:List-post: List-archive; b=D866JLpn8EKuiGRwUA6OWcnpxipd7zS7uaMp73utOakr2/906QBRkxPaY1o5C29KK vdZZ8fwbJT1VvzFgwoPITkKjQ+yEp9LjYnU1xhbkcxNbXHjCbDqK4Vt52f9oPiPMfn NdWQdcDqLDq7zqN/41Gb9Zgc8OrHiruuZl3fnirs= X-Original-To: patchew-devel@freelists.org X-Virus-Scanned: Debian amavisd-new at turing.freelists.org X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:subject:date:message-id :in-reply-to:references; bh=xMux4HtlHc5yORzLzkJhaeITJ9S4pkotopj5COMdbWg=; b=V0Jrmx01/jOJ1tj+SGAZ8rK7lD+YFf0K4Izfy5DKJtde7cEnzfSRAUBeZObkZDJ0u8 rRjjGxKc+/HLFSSOOjvXbqLyFq70sKfV/kNHctpJxe9XxnOXmeSgLr0fVNB0bQBx5F3U AZwoxNP76RbM2ijHlulGIkxvPz0puMwU8xi8/rqcYGcDbRYE6Fes4XTYRBSYyT9XzeXZ T2SA6+OVKsELnqNsfk9AyJ7gNgi8BZ8JYGjxTNJ38wFImrdft3qLrwZMdA1wsk7Gez3f gyYNyRpPGdK2e+R9P51Q4y2Z6ixSl0KicJlM0jvGsR2Wdu3wxSjMc4S2m+oTtRIXCuyR TA7A== X-Gm-Message-State: AElRT7ETuosGC9HKyba0AHpqSOIvH6dI0dgdzK07TBvtb42WYfVifAGv WnI/smL/RYrVSfR1bEpIEe3VX6zj X-Google-Smtp-Source: AG47ELvpHt7PC/AZ4WfzWJ2nt7SLKh/F3kz2TVEiKEI6ZjmWgkCr6iv1kv641YvTbbi3mO/sa9Wcew== X-Received: by 10.28.29.209 with SMTP id d200mr8197735wmd.149.1520241396279; Mon, 05 Mar 2018 01:16:36 -0800 (PST) From: Paolo Bonzini To: patchew-devel@freelists.org Subject: [patchew-devel] [PATCH 2/6] ansi2html: create ANSIProcessor superclass Date: Mon, 5 Mar 2018 10:16:30 +0100 Message-Id: <20180305091634.7391-3-pbonzini@redhat.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180305091634.7391-1-pbonzini@redhat.com> References: <20180305091634.7391-1-pbonzini@redhat.com> X-archive-position: 74 X-ecartis-version: Ecartis v1.0.0 Sender: patchew-devel-bounce@freelists.org Errors-to: patchew-devel-bounce@freelists.org X-original-sender: pbonzini@redhat.com Precedence: normal Reply-To: patchew-devel@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: patchew-devel X-List-ID: patchew-devel List-subscribe: List-owner: List-post: List-archive: X-list: patchew-devel X-ZohoMail-DKIM: pass (identity @freelists.org) X-ZohoMail: RDKM_0 RSF_4 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Paolo Bonzini --- patchew/logviewer.py | 216 ++++++++++++++++++++++++++++-------------------= ---- 1 file changed, 120 insertions(+), 96 deletions(-) diff --git a/patchew/logviewer.py b/patchew/logviewer.py index ab5f5c3..aa5d2bb 100644 --- a/patchew/logviewer.py +++ b/patchew/logviewer.py @@ -15,38 +15,18 @@ from django.views import View from django.http import HttpResponse, StreamingHttpResponse from django.utils.safestring import mark_safe =20 -class ANSI2HTMLConverter(object): +class ANSIProcessor(object): RE_STRING =3D '[^\b\t\n\f\r\x1B]+' RE_NUMS =3D '[0-9]+(?:;[0-9]+)*' RE_CSI =3D r'\[\??(?:' + RE_NUMS + ')?[^;0-9]' RE_OSC =3D r'].*?(?:\x1B\\|\x07)' RE_CONTROL =3D '\x1B(?:%s|%s|[^][])|\r\n|[\b\t\n\f\r]' % (RE_CSI, RE_O= SC) RE =3D re.compile('(%s)|(%s)' % (RE_STRING, RE_CONTROL)) - COLORS =3D [ "BLK", "RED", "GRN", "YEL", "BLU", "MAG", "CYN", "WHI", - "HIK", "HIR", "HIG", "HIY", "HIB", "HIM", "HIC", "HIW" ] - - ENTITIES =3D { - '\x00' : '␀', '\x01' : '␁', '\x02' : '␂', - '\x03' : '␃', '\x04' : '␄', '\x05' : '␅', - '\x06' : '␆', '\x07' : '🔔', '\x0B' : '␋', - '\x0E' : '␎', '\x0F' : '␏', '\x10' : '␐', - '\x11' : '␑', '\x12' : '␒', '\x13' : '␓', - '\x14' : '␔', '\x15' : '␕', '\x16' : '␖', - '\x17' : '␗', '\x18' : '␘', '\x19' : '␙', - '\x1A' : '␚', '\x1B' : '␛', '\x1C' : '␜', - '\x1D' : '␝', '\x1E' : '␞', '\x1F' : '␟', - '<' : '<', '>' : '>', '&' : '&', - '\x7F' : '⌦' - } - RE_ENTITIES =3D re.compile('[\x00-\x1F<>&\x7F]') =20 - def __init__(self, white_bg=3DFalse): + def __init__(self): self.class_to_id =3D {} self.id_to_class =3D [] - self.default_fg =3D 0 if white_bg else 7 - self.default_bg =3D 7 if white_bg else 0 self.cur_class =3D self._class_to_id("") - self.prefix =3D '
'
         self._reset()
         self._reset_attrs()
=20
@@ -99,17 +79,9 @@ class ANSI2HTMLConverter(object):
             self.line +=3D [' '] * num
             self.class_ids +=3D [0] * num
=20
-    def _write_prefix(self):
-        if self.prefix !=3D '':
-            yield self.prefix
-            self.prefix =3D ''
-
+    @abc.abstractmethod
     def _write_span(self, text, class_id):
-        if class_id > 0:
-            yield ('' % self.id_to_class[class_id])
-        yield self.RE_ENTITIES.sub(lambda x: self.ENTITIES[x.group(0)], te=
xt)
-        if class_id > 0:
-            yield ''
+        pass
=20
     # Flushing a line locates spans that have the same style, and prints t=
hose
     # with a  tag if they are styled.
@@ -198,7 +170,7 @@ class ANSI2HTMLConverter(object):
             self.bg =3D arg - 92
=20
     def _write_form_feed(self):
-        yield '
' + pass =20 def _class_to_id(self, html_class): class_id =3D self.class_to_id.get(html_class, None) @@ -208,67 +180,8 @@ class ANSI2HTMLConverter(object): self.id_to_class.append(html_class) return class_id =20 - def _map_color(self, color, default, dim): - # map a color assigned by _do_one_csi_m to an index in the COLORS = array - - color =3D color if color is not None else default - if dim: - # must be foreground color - if isinstance(color, int): - # unlike vte which has a "very dark" grey, for simplicity - # dark grey remains dark grey - return 8 if color =3D=3D default or color =3D=3D 8 else co= lor&~8 - else: - return ('d' + color[0], 'd' + color[1]) - else: - if isinstance(color, int): - # use light colors by default, except for black and light = grey - # (but see bold case in _compute_class) - return color if color =3D=3D 0 or color =3D=3D 7 else colo= r|8 - else: - return color - def _compute_class(self): - fg =3D self._map_color(self.fg, self.default_fg, self.dim) - bg =3D self._map_color(self.bg, self.default_bg, False) - - # apply inverse now: "inverse dim" affects the *background* color! - if self.inverse: - fg, bg =3D bg, fg - - # bold turns foreground light grey into white - if fg =3D=3D 7 and not self.dim and self.bold: - fg =3D 15 - - # now compute CSS classes - classes =3D [] - if isinstance(fg, int): - if fg !=3D self.default_fg: - classes.append(self.COLORS[fg]) - else: - # 256-color palette - classes.append(fg[0]) - - if isinstance(bg, int): - if bg !=3D self.default_bg: - classes.append('B' + self.COLORS[bg]) - else: - classes.append(bg[1]) - - if self.bold: - classes.append('BOLD') - if self.italic: - classes.append('ITA') - - if self.underline or self.strike: - undstr =3D '' - if self.underline: - undstr +=3D 'UND' - if self.strike: - undstr +=3D 'STR' - classes.append(undstr) - - self.cur_class =3D self._class_to_id(" ".join(classes)) + pass =20 def _do_csi_m(self, it): try: @@ -335,7 +248,6 @@ class ANSI2HTMLConverter(object): self._parse_csi_with_args(csi, self._do_csi_m) =20 def convert(self, input): - yield from self._write_prefix() for m in self.RE.finditer(input): if m.group(1): if self.lazy_accumulate: @@ -369,11 +281,123 @@ class ANSI2HTMLConverter(object): elif len(seq) > 1: yield from self._parse_csi(seq) =20 + def finish(self): + yield from self._write_line('') + self._reset_attrs() + + +class ANSI2HTMLConverter(ANSIProcessor): + ENTITIES =3D { + '\x00' : '␀', '\x01' : '␁', '\x02' : '␂', + '\x03' : '␃', '\x04' : '␄', '\x05' : '␅', + '\x06' : '␆', '\x07' : '🔔', '\x0B' : '␋', + '\x0E' : '␎', '\x0F' : '␏', '\x10' : '␐', + '\x11' : '␑', '\x12' : '␒', '\x13' : '␓', + '\x14' : '␔', '\x15' : '␕', '\x16' : '␖', + '\x17' : '␗', '\x18' : '␘', '\x19' : '␙', + '\x1A' : '␚', '\x1B' : '␛', '\x1C' : '␜', + '\x1D' : '␝', '\x1E' : '␞', '\x1F' : '␟', + '<' : '<', '>' : '>', '&' : '&', + '\x7F' : '⌦' + } + RE_ENTITIES =3D re.compile('[\x00-\x1F<>&\x7F]') + + COLORS =3D [ "BLK", "RED", "GRN", "YEL", "BLU", "MAG", "CYN", "WHI", + "HIK", "HIR", "HIG", "HIY", "HIB", "HIM", "HIC", "HIW" ] + + def __init__(self, white_bg=3DFalse): + super(ANSI2HTMLConverter, self).__init__() + self.default_fg =3D 0 if white_bg else 7 + self.default_bg =3D 7 if white_bg else 0 + self.prefix =3D '
'
+
+    def _write_prefix(self):
+        if self.prefix !=3D '':
+            yield self.prefix
+            self.prefix =3D ''
+
+    def _map_color(self, color, default, dim):
+        # map a color assigned by _do_one_csi_m to an index in the COLORS =
array
+
+        color =3D color if color is not None else default
+        if dim:
+            # must be foreground color
+            if isinstance(color, int):
+                # unlike vte which has a "very dark" grey, for simplicity
+                # dark grey remains dark grey
+                return 8 if color =3D=3D default or color =3D=3D 8 else co=
lor&~8
+            else:
+                return ('d' + color[0], 'd' + color[1])
+        else:
+            if isinstance(color, int):
+                # use light colors by default, except for black and light =
grey
+                # (but see bold case in _compute_class)
+                return color if color =3D=3D 0 or color =3D=3D 7 else colo=
r|8
+            else:
+                return color
+
+    def _compute_class(self):
+        fg =3D self._map_color(self.fg, self.default_fg, self.dim)
+        bg =3D self._map_color(self.bg, self.default_bg, False)
+
+        # apply inverse now: "inverse dim" affects the *background* color!
+        if self.inverse:
+            fg, bg =3D bg, fg
+
+        # bold turns foreground light grey into white
+        if fg =3D=3D 7 and not self.dim and self.bold:
+            fg =3D 15
+
+        # now compute CSS classes
+        classes =3D []
+        if isinstance(fg, int):
+            if fg !=3D self.default_fg:
+                classes.append(self.COLORS[fg])
+        else:
+            # 256-color palette
+            classes.append(fg[0])
+
+        if isinstance(bg, int):
+            if bg !=3D self.default_bg:
+                classes.append('B' + self.COLORS[bg])
+        else:
+            classes.append(bg[1])
+
+        if self.bold:
+            classes.append('BOLD')
+        if self.italic:
+            classes.append('ITA')
+
+        if self.underline or self.strike:
+            undstr =3D ''
+            if self.underline:
+                undstr +=3D 'UND'
+            if self.strike:
+                undstr +=3D 'STR'
+            classes.append(undstr)
+
+        self.cur_class =3D self._class_to_id(" ".join(classes))
+
+    def _write_span(self, text, class_id):
+        if class_id > 0:
+            yield ('' % self.id_to_class[class_id])
+        yield self.RE_ENTITIES.sub(lambda x: self.ENTITIES[x.group(0)], te=
xt)
+        if class_id > 0:
+            yield ''
+
+    def _write_form_feed(self):
+        yield '
' + + def convert(self, input): + yield from self._write_prefix() + yield from super(ANSI2HTMLConverter, self).convert(input) + def finish(self): yield from self._write_prefix() - yield from self._write_line('
') + yield from super(ANSI2HTMLConverter, self).finish() + yield '
' self.prefix =3D '
'
-        self._reset_attrs()
+
=20
 def ansi2html(input, white_bg=3DFalse):
     c =3D ANSI2HTMLConverter(white_bg=3Dwhite_bg)
--=20
2.14.3



From nobody Thu May  2 15:14:31 2024
Delivered-To: importer@patchew.org
Received-SPF: none (zoho.com: 206.53.239.180 is neither permitted nor denied
 by domain of freelists.org) client-ip=206.53.239.180;
 envelope-from=patchew-devel-bounce@freelists.org; helo=turing.freelists.org;
Authentication-Results: mx.zohomail.com;
	dkim=pass;
	spf=none (zoho.com: 206.53.239.180 is neither permitted nor denied by domain
 of freelists.org)  smtp.mailfrom=patchew-devel-bounce@freelists.org;
	dmarc=fail(p=none dis=none)  header.from=redhat.com
Return-Path: 
Received: from turing.freelists.org (turing.freelists.org [206.53.239.180]) by
 mx.zohomail.com
	with SMTPS id 1520241400476626.1045934352479;
 Mon, 5 Mar 2018 01:16:40 -0800 (PST)
Received: from localhost (localhost [127.0.0.1])
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id
 E3D4C27251;
	Mon,  5 Mar 2018 04:16:39 -0500 (EST)
Received: from turing.freelists.org ([127.0.0.1])
	by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024)
	with ESMTP id D5F6zmvWkI7R; Mon,  5 Mar 2018 04:16:39 -0500 (EST)
Received: from turing.freelists.org (localhost [127.0.0.1])
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id
 98F5326402;
	Mon,  5 Mar 2018 04:16:39 -0500 (EST)
Received: with ECARTIS (v1.0.0; list patchew-devel);
 Mon, 05 Mar 2018 04:16:39 -0500 (EST)
Received: from localhost (localhost [127.0.0.1])
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id
 645E427251
	for ; Mon,  5 Mar 2018 04:16:39 -0500 (EST)
Received: from turing.freelists.org ([127.0.0.1])
	by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024)
	with ESMTP id ez5ODg8m322M for ;
	Mon,  5 Mar 2018 04:16:39 -0500 (EST)
Received: from mail-wr0-f175.google.com (mail-wr0-f175.google.com
 [209.85.128.175])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id
 F405126402
	for ; Mon,  5 Mar 2018 04:16:38 -0500 (EST)
Received: by mail-wr0-f175.google.com with SMTP id f14so16399264wre.8
        for ;
 Mon, 05 Mar 2018 01:16:38 -0800 (PST)
Received: from donizetti.lan (94-36-191-219.adsl-ull.clienti.tiscali.it.
 [94.36.191.219])
        by smtp.gmail.com with ESMTPSA id
 b68sm7018546wmi.30.2018.03.05.01.16.36
        for 
        (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256);
        Mon, 05 Mar 2018 01:16:36 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=freelists.org;
	s=turing; t=1520241399;
	bh=TjbRQ8qKSyUOqFRnomiXCpQuAcF5JlYJPV++1G5xOZM=;
	h=From:To:Subject:Date:In-Reply-To:References:Reply-To:List-help:
	 List-unsubscribe:List-Id:List-subscribe:List-owner:List-post:
	 List-archive;
	b=fxvDPsCyb7pJ0DWKgqZPh/xSOUxY9ED+uFv0LFAFvN2GxuKZ+XlnkYl/DiFp9kwo4
	 Pa4m2NUvu/wRrX/dS3hjODSncKy5jg0ulBg8r/ClgGeGv4cN3ybOfB60SxNbyD07vR
	 qiX0IGCQsjvnYIoKZvjiEa4Un1G8YVQe+el7wYCc=
X-Virus-Scanned: Debian amavisd-new at turing.freelists.org
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=freelists.org;
	s=turing; t=1520241399;
	bh=TjbRQ8qKSyUOqFRnomiXCpQuAcF5JlYJPV++1G5xOZM=;
	h=From:To:Subject:Date:In-Reply-To:References:Reply-To:List-help:
	 List-unsubscribe:List-Id:List-subscribe:List-owner:List-post:
	 List-archive;
	b=fxvDPsCyb7pJ0DWKgqZPh/xSOUxY9ED+uFv0LFAFvN2GxuKZ+XlnkYl/DiFp9kwo4
	 Pa4m2NUvu/wRrX/dS3hjODSncKy5jg0ulBg8r/ClgGeGv4cN3ybOfB60SxNbyD07vR
	 qiX0IGCQsjvnYIoKZvjiEa4Un1G8YVQe+el7wYCc=
X-Original-To: patchew-devel@freelists.org
X-Virus-Scanned: Debian amavisd-new at turing.freelists.org
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:sender:from:to:subject:date:message-id
         :in-reply-to:references;
        bh=IfqI7qxse1PNe+y8kZzVVrioZfRIsfVTsmty1IdkvvE=;
        b=czPpSd5hvAx0MFYe7uWlU8m1/DBBZDI04Bf45aNPEd2qs6kCEA3VPMXLO4kKXKZ8qf
         JSjIXKTejIZBl/SFzGRRXnm2+3aUu91JobXGuZwxPq74dcIjLZFadLE2z+VPkvo+l8gK
         K7ptDCfwqgNBkVDeB4rMv70/mF/Aw0rs+P/uroWals5xM+mWK9r2IqRtkxSp5n3U4R/M
         N0Vahzl76LzgsCxkWr2bp+Fl98VAolwijimK0l6HcvZaavSaiwqxqW1EAbD2ZWF72l8u
         atIUSmS8DILWn47Ca8XNjHPpfPVwtz/NB9IyDukoecQJUR2YPaQFI/VRvmGAO6/fbZb/
         rLpw==
X-Gm-Message-State: APf1xPAaV2KqG8XGSUJbucZCLf8gDqT+R7duDOdlOiLqADL1ZB3d/El3
	28zVQFKMOB4Da0SjXJOKi6yhqoiW
X-Google-Smtp-Source: 
 AG47ELsoS8MqcgN+uPvxuNdJz19CQHdZMeXme9QEqHG8ceLhORSdqH0WMJ6FJJF3n7YWRm5VgR2LiQ==
X-Received: by 10.223.160.243 with SMTP id n48mr12437603wrn.92.1520241397302;
        Mon, 05 Mar 2018 01:16:37 -0800 (PST)
From: Paolo Bonzini 
To: patchew-devel@freelists.org
Subject: [patchew-devel] [PATCH 3/6] ansi2html: create ANSI to text converter
Date: Mon,  5 Mar 2018 10:16:31 +0100
Message-Id: <20180305091634.7391-4-pbonzini@redhat.com>
X-Mailer: git-send-email 2.14.3
In-Reply-To: <20180305091634.7391-1-pbonzini@redhat.com>
References: <20180305091634.7391-1-pbonzini@redhat.com>
X-archive-position: 75
X-ecartis-version: Ecartis v1.0.0
Sender: patchew-devel-bounce@freelists.org
Errors-to: patchew-devel-bounce@freelists.org
X-original-sender: pbonzini@redhat.com
Precedence: normal
Reply-To: patchew-devel@freelists.org
List-help: 
List-unsubscribe: 
List-software: Ecartis version 1.0.0
List-Id: patchew-devel 
X-List-ID: patchew-devel 
List-subscribe: 
List-owner: 
List-post: 
List-archive: 
X-list: patchew-devel
X-ZohoMail-DKIM: pass (identity @freelists.org)
X-ZohoMail: RDKM_0  RSF_4  Z_629925259 SPT_0
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"

This converter compresses sequences involving carriage returns or backspace=
s,
to make them readable from an editor or mail reader.

Signed-off-by: Paolo Bonzini 
---
 patchew/logviewer.py      | 29 ++++++++++++++++++
 patchew/settings.py       |  3 ++
 patchew/tags.py           | 19 ++++++++++++
 tests/test_ansi2html.py   | 75 +++++++++++++++++++++++++++++++++++++++++++=
+++-
 tests/test_custom_tags.py | 27 +++++++++++++++++
 5 files changed, 152 insertions(+), 1 deletion(-)
 create mode 100644 patchew/tags.py
 create mode 100755 tests/test_custom_tags.py

diff --git a/patchew/logviewer.py b/patchew/logviewer.py
index aa5d2bb..b84d487 100644
--- a/patchew/logviewer.py
+++ b/patchew/logviewer.py
@@ -286,6 +286,29 @@ class ANSIProcessor(object):
         self._reset_attrs()
=20
=20
+class ANSI2TextConverter(ANSIProcessor):
+    FF =3D '\u2015' * 72 + '\n'
+    SYMBOLS =3D {
+        '\x00' : '\u2400', '\x01' : '\u2401',      '\x02' : '\u2402',
+        '\x03' : '\u2403', '\x04' : '\u2404',      '\x05' : '\u2405',
+        '\x06' : '\u2406', '\x07' : '\U00001F514', '\x0B' : '\u240B',
+        '\x0E' : '\u240E', '\x0F' : '\u240F',      '\x10' : '\u2410',
+        '\x11' : '\u2411', '\x12' : '\u2412',      '\x13' : '\u2413',
+        '\x14' : '\u2414', '\x15' : '\u2415',      '\x16' : '\u2416',
+        '\x17' : '\u2417', '\x18' : '\u2418',      '\x19' : '\u2419',
+        '\x1A' : '\u241A', '\x1B' : '\u241B',      '\x1C' : '\u241C',
+        '\x1D' : '\u241D', '\x1E' : '\u241E',      '\x1F' : '\u241F',
+        '\x7F' : '\u2326'
+    }
+    RE_SYMBOLS =3D re.compile('[\x00-\x1F\x7F]')
+
+    def _write_span(self, text, class_id):
+        yield self.RE_SYMBOLS.sub(lambda x: self.SYMBOLS[x.group(0)], text)
+
+    def _write_form_feed(self):
+        yield self.FF
+
+
 class ANSI2HTMLConverter(ANSIProcessor):
     ENTITIES =3D {
         '\x00' : '␀', '\x01' : '␁',  '\x02' : '␂',
@@ -399,6 +422,12 @@ class ANSI2HTMLConverter(ANSIProcessor):
         self.prefix =3D '
'
=20
=20
+def ansi2text(input):
+    c =3D ANSI2TextConverter()
+    yield from c.convert(input)
+    yield from c.finish()
+
+
 def ansi2html(input, white_bg=3DFalse):
     c =3D ANSI2HTMLConverter(white_bg=3Dwhite_bg)
     yield from c.convert(input)
diff --git a/patchew/settings.py b/patchew/settings.py
index 90a28c3..65a3b29 100644
--- a/patchew/settings.py
+++ b/patchew/settings.py
@@ -84,6 +84,9 @@ TEMPLATES =3D [
                 'django.contrib.auth.context_processors.auth',
                 'django.contrib.messages.context_processors.messages',
             ],
+            'builtins': [
+                'patchew.tags',
+            ],
         },
     },
 ]
diff --git a/patchew/tags.py b/patchew/tags.py
new file mode 100644
index 0000000..22d64b0
--- /dev/null
+++ b/patchew/tags.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python3
+#
+# Copyright 2018 Red Hat, Inc.
+#
+# Authors:
+#     Paolo Bonzini 
+#
+# This work is licensed under the MIT License.  Please see the LICENSE fil=
e or
+# http://opensource.org/licenses/MIT.
+
+from django import template
+from patchew import logviewer
+
+register =3D template.Library()
+
+@register.simple_tag
+@register.filter
+def ansi2text(value):
+    return ''.join(logviewer.ansi2text(value))
diff --git a/tests/test_ansi2html.py b/tests/test_ansi2html.py
index cb709fd..e146c3e 100644
--- a/tests/test_ansi2html.py
+++ b/tests/test_ansi2html.py
@@ -6,7 +6,7 @@
=20
 import unittest
=20
-from patchew.logviewer import ansi2html
+from patchew.logviewer import ansi2html, ansi2text, ANSI2TextConverter
=20
 class ANSI2HTMLTest(unittest.TestCase):
     def assertAnsi(self, test, expected, **kwargs):
@@ -291,5 +291,78 @@ class ANSI2HTMLTest(unittest.TestCase):
         self.assertWhiteBg('abc\x1b[7m\x1b[1Kabc', '   abc')
=20
=20
+class ANSI2TextTest(unittest.TestCase):
+    def assertAnsi(self, test, expected, **kwargs):
+        self.assertEqual(''.join(ansi2text(test, **kwargs)), expected,
+                         repr(test))
+
+    # basic formatting tests
+    def test_basic(self):
+        self.assertAnsi('\tb', '        b')
+        self.assertAnsi('\t\ta', '                a')
+        self.assertAnsi('a\tb', 'a       b')
+        self.assertAnsi('ab\tc', 'ab      c')
+        self.assertAnsi('a\nbc', 'a\nbc')
+        self.assertAnsi('a\f', 'a\n' + ANSI2TextConverter.FF)
+        self.assertAnsi('a\n\f', 'a\n\n' + ANSI2TextConverter.FF)
+        self.assertAnsi('<', '<')
+        self.assertAnsi('\x07', '\U00001F514')
+
+    # backspace and carriage return
+    def test_set_pos(self):
+        self.assertAnsi('abc\b\bBC', 'aBC')
+        self.assertAnsi('a\b<', '<')
+        self.assertAnsi('<\ba', 'a')
+        self.assertAnsi('a\b\bbc', 'bc')
+        self.assertAnsi('a\rbc', 'bc')
+        self.assertAnsi('a\nb\bc', 'a\nc')
+        self.assertAnsi('a\t\bb', 'a      b')
+        self.assertAnsi('a\tb\b\bc', 'a      cb')
+        self.assertAnsi('01234567\r\tb', '01234567b')
+
+    # Escape sequences
+    def test_esc_parsing(self):
+        self.assertAnsi('{\x1b%}', '{}')
+        self.assertAnsi('{\x1b[0m}', '{}')
+        self.assertAnsi('{\x1b[m}', '{}')
+        self.assertAnsi('{\x1b[0;1;7;0m}', '{}')
+        self.assertAnsi('{\x1b[1;7m\x1b[m}', '{}')
+        self.assertAnsi('{\x1b]test\x1b\\}', '{}')
+        self.assertAnsi('{\x1b]test\x07}', '{}')
+        self.assertAnsi('{\x1b]test\x1b[0m\x07}', '{}')
+        self.assertAnsi('{\x1b]test\x1b[7m\x07}', '{}')
+
+    # ESC [C and ESC [D
+    def test_horiz_movement(self):
+        self.assertAnsi('abc\x1b[2DB', 'aBc')
+        self.assertAnsi('abc\x1b[3CD', 'abc   D')
+        self.assertAnsi('abcd\x1b[3DB\x1b[1CD', 'aBcD')
+        self.assertAnsi('abc\x1b[0CD', 'abc D')
+        self.assertAnsi('abc\x1b[CD', 'abc D')
+
+    # ESC [K
+    def test_clear_line(self):
+        self.assertAnsi('\x1b[Kabcd', 'abcd')
+        self.assertAnsi('abcd\r\x1b[K', '')
+        self.assertAnsi('abcd\b\x1b[K', 'abc')
+        self.assertAnsi('abcd\r\x1b[KDef', 'Def')
+        self.assertAnsi('abcd\b\x1b[KDef', 'abcDef')
+        self.assertAnsi('abcd\r\x1b[0K', '')
+        self.assertAnsi('abcd\b\x1b[0K', 'abc')
+        self.assertAnsi('abcd\r\x1b[1K', 'abcd')
+        self.assertAnsi('abcd\b\x1b[1K', '   d')
+        self.assertAnsi('abcd\r\x1b[2K', '')
+        self.assertAnsi('abcd\b\x1b[2K', '   ')
+        self.assertAnsi('abcd\r\x1b[2KDef', 'Def')
+        self.assertAnsi('abcd\b\x1b[2KDef', '   Def')
+
+    # combining cursor movement and formatting
+    def test_movement_and_formatting(self):
+        self.assertAnsi('\x1b[42m\tabc', '        abc')
+        self.assertAnsi('abc\x1b[42m\x1b[1Kabc', '   abc')
+        self.assertAnsi('\x1b[7m\tabc', '        abc')
+        self.assertAnsi('abc\x1b[7m\x1b[1Kabc', '   abc')
+
+
 if __name__ =3D=3D '__main__':
     unittest.main()
diff --git a/tests/test_custom_tags.py b/tests/test_custom_tags.py
new file mode 100755
index 0000000..ec875c8
--- /dev/null
+++ b/tests/test_custom_tags.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+#
+# Copyright 2018 Red Hat, Inc.
+#
+# Authors:
+#     Paolo Bonzini 
+#
+# This work is licensed under the MIT License.  Please see the LICENSE fil=
e or
+# http://opensource.org/licenses/MIT.
+
+from django.template import Context, Template
+import patchewtest
+import unittest
+
+class CustomTagsTest(unittest.TestCase):
+    def assertTemplate(self, template, expected, **kwargs):
+        context =3D Context(kwargs)
+        self.assertEqual(Template(template).render(context), expected)
+
+    def test_template_filters(self):
+        self.assertTemplate('{{s|ansi2text}}', 'dbc', s=3D'abc\rd')
+
+    def test_template_tags(self):
+        self.assertTemplate('{% ansi2text s %}', 'dbc', s=3D'abc\rd')
+
+if __name__ =3D=3D '__main__':
+    unittest.main()
--=20
2.14.3



From nobody Thu May  2 15:14:31 2024
Delivered-To: importer@patchew.org
Received-SPF: none (zoho.com: 206.53.239.180 is neither permitted nor denied
 by domain of freelists.org) client-ip=206.53.239.180;
 envelope-from=patchew-devel-bounce@freelists.org; helo=turing.freelists.org;
Authentication-Results: mx.zohomail.com;
	dkim=pass;
	spf=none (zoho.com: 206.53.239.180 is neither permitted nor denied by domain
 of freelists.org)  smtp.mailfrom=patchew-devel-bounce@freelists.org;
	dmarc=fail(p=none dis=none)  header.from=redhat.com
Return-Path: 
Received: from turing.freelists.org (turing.freelists.org [206.53.239.180]) by
 mx.zohomail.com
	with SMTPS id 1520241401706573.7399030526839;
 Mon, 5 Mar 2018 01:16:41 -0800 (PST)
Received: from localhost (localhost [127.0.0.1])
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id
 2E33C272AA;
	Mon,  5 Mar 2018 04:16:41 -0500 (EST)
Received: from turing.freelists.org ([127.0.0.1])
	by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024)
	with ESMTP id 8sWUNxMyzYFr; Mon,  5 Mar 2018 04:16:41 -0500 (EST)
Received: from turing.freelists.org (localhost [127.0.0.1])
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id
 D67A426402;
	Mon,  5 Mar 2018 04:16:40 -0500 (EST)
Received: with ECARTIS (v1.0.0; list patchew-devel);
 Mon, 05 Mar 2018 04:16:40 -0500 (EST)
Received: from localhost (localhost [127.0.0.1])
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id
 9DE57272AA
	for ; Mon,  5 Mar 2018 04:16:40 -0500 (EST)
Received: from turing.freelists.org ([127.0.0.1])
	by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024)
	with ESMTP id ElfG3r31yd_B for ;
	Mon,  5 Mar 2018 04:16:40 -0500 (EST)
Received: from mail-wm0-f41.google.com (mail-wm0-f41.google.com
 [74.125.82.41])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id
 39BCF26402
	for ; Mon,  5 Mar 2018 04:16:40 -0500 (EST)
Received: by mail-wm0-f41.google.com with SMTP id t3so14282857wmc.2
        for ;
 Mon, 05 Mar 2018 01:16:40 -0800 (PST)
Received: from donizetti.lan (94-36-191-219.adsl-ull.clienti.tiscali.it.
 [94.36.191.219])
        by smtp.gmail.com with ESMTPSA id
 b68sm7018546wmi.30.2018.03.05.01.16.37
        for 
        (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256);
        Mon, 05 Mar 2018 01:16:37 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=freelists.org;
	s=turing; t=1520241401;
	bh=WJHso6LipgLGC/bmMlh6srmMJzmOln13rjUVKOx1j1s=;
	h=From:To:Subject:Date:In-Reply-To:References:Reply-To:List-help:
	 List-unsubscribe:List-Id:List-subscribe:List-owner:List-post:
	 List-archive;
	b=pYfa+fG3MGWbcfjJe77/eN0Mkbcis42fZAgT04DhhjMlseJ/6YAiBukom3fUG05U3
	 zk/vzHGrhOkjfXo1s9BEYFgriYE8r3uUqnMO+F02M85m1lMW3HY2Om10aUEPrMPjVM
	 K/ira4PR8//ByB3tSaOXKqy0tJNQ4L0Rm6y2WNsY=
X-Virus-Scanned: Debian amavisd-new at turing.freelists.org
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=freelists.org;
	s=turing; t=1520241401;
	bh=WJHso6LipgLGC/bmMlh6srmMJzmOln13rjUVKOx1j1s=;
	h=From:To:Subject:Date:In-Reply-To:References:Reply-To:List-help:
	 List-unsubscribe:List-Id:List-subscribe:List-owner:List-post:
	 List-archive;
	b=pYfa+fG3MGWbcfjJe77/eN0Mkbcis42fZAgT04DhhjMlseJ/6YAiBukom3fUG05U3
	 zk/vzHGrhOkjfXo1s9BEYFgriYE8r3uUqnMO+F02M85m1lMW3HY2Om10aUEPrMPjVM
	 K/ira4PR8//ByB3tSaOXKqy0tJNQ4L0Rm6y2WNsY=
X-Original-To: patchew-devel@freelists.org
X-Virus-Scanned: Debian amavisd-new at turing.freelists.org
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:sender:from:to:subject:date:message-id
         :in-reply-to:references;
        bh=splG6LFX44urde7Xd2TOdZqWGX7yJqovZ0oKSsyayek=;
        b=Tm04ChrcBq7453iqILf6VwR2XF5izjtTKg1KJRyewF/WpgQF6pW2oVAyvoal26pI47
         /ig8eDX97dZcTUWyrJbi6oNEfR4CqEzLD46BaUyr0mjC1S65f18H/BfAUKuPL6l3BbTP
         Nkrcaqki4ZXiweTcvWeZaouBRkdxy8VES+E3HEd9pgl68ylYPdlqcCoKEGkxoaGp/uWg
         RCtdWtkUWy4yLN8XGFkIlkFqaO0AVE+2tGf3jJ7lJtU71xkrg2Zkp8up+DpjOqLyYn8+
         eFixDcrVmvZVob2U1BffE1LmmooW6LNQuUxlg4GTR2Bcx9exWbJfnmtwa88XbC4sdGFc
         Z+7w==
X-Gm-Message-State: AElRT7Fp6FzQ/VZ9DvjzXuAj4oXoxd05zLA6j9yFn+ma1RmqWI3N3+YD
	WuskMRlHjTsi+jrjcJbMV4Fe0hU9
X-Google-Smtp-Source: 
 AG47ELsCFxP6F7dQWcMWZUAx9yC9vLWp7lnQqGlDBoyzRu2fP4+U5DiqPiT4GJL6b6xF9iVC+kJy8w==
X-Received: by 10.28.138.6 with SMTP id m6mr8111505wmd.146.1520241398523;
        Mon, 05 Mar 2018 01:16:38 -0800 (PST)
From: Paolo Bonzini 
To: patchew-devel@freelists.org
Subject: [patchew-devel] [PATCH 4/6] add custom template tags for manipulating
 testing logs
Date: Mon,  5 Mar 2018 10:16:32 +0100
Message-Id: <20180305091634.7391-5-pbonzini@redhat.com>
X-Mailer: git-send-email 2.14.3
In-Reply-To: <20180305091634.7391-1-pbonzini@redhat.com>
References: <20180305091634.7391-1-pbonzini@redhat.com>
X-archive-position: 76
X-ecartis-version: Ecartis v1.0.0
Sender: patchew-devel-bounce@freelists.org
Errors-to: patchew-devel-bounce@freelists.org
X-original-sender: pbonzini@redhat.com
Precedence: normal
Reply-To: patchew-devel@freelists.org
List-help: 
List-unsubscribe: 
List-software: Ecartis version 1.0.0
List-Id: patchew-devel 
X-List-ID: patchew-devel 
List-subscribe: 
List-owner: 
List-post: 
List-archive: 
X-list: patchew-devel
X-ZohoMail-DKIM: pass (identity @freelists.org)
X-ZohoMail: RDKM_0  RSF_4  Z_629925259 SPT_0
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"

These can be used to make test report emails shorter and more readable.

Signed-off-by: Paolo Bonzini 
---
 patchew/tags.py           |  77 ++++++++++++++++++++++++++++++++++
 tests/test_custom_tags.py | 102 ++++++++++++++++++++++++++++++++++++++++++=
++++
 2 files changed, 179 insertions(+)

diff --git a/patchew/tags.py b/patchew/tags.py
index 22d64b0..4847cb4 100644
--- a/patchew/tags.py
+++ b/patchew/tags.py
@@ -10,6 +10,57 @@
=20
 from django import template
 from patchew import logviewer
+from collections import deque
+import io
+import operator
+import re
+
+# The basic implementation uses generators.  The filters simply apply join
+# to the result of the generators.
+
+def lines_iter(value):
+    if not isinstance(value, io.IOBase):
+        # StringIO provides a generator to split lines.
+        value =3D io.StringIO(value)
+    # "chomp" the newlines on each line.  Using operator and map does
+    # everything in the interpreter, avoiding the overhead of a generator.
+    return map(operator.methodcaller('rstrip', '\r\n'), value)
+
+# To understand grep_iter, it may help to first study this implementation
+# of a "tail" iterator, which is based on the same circular array idea:
+#
+#    def tail_lines_iter(value, n):
+#        lines =3D [None] * n
+#        lineno =3D 0
+#        for line in lines_iter(value):
+#            lines[lineno % n] =3D line
+#            lineno +=3D 1
+#
+#        for i in range(max(lineno - n, 0), lineno):
+#            yield lines[i % n]
+#
+# Basic "grep" prints one line when the match is on the last line, so
+# "grep" is a variation on tail_lines with n=3D1; likewise, "grep -B1" is
+# a variantion on tail_lines with n=3D2, etc.
+
+def grep_iter(value, regex, n_before, n_after, sep):
+    n =3D n_before + 1
+    lines =3D [None] * n
+    stop =3D lineno =3D 0
+    for line in lines_iter(value):
+        # Print the (lineno - n)-th line.  Each element of lines[] is used
+        # just before it is thrown away.
+        if lineno - n >=3D 0 and lineno - n < stop:
+            yield lines[lineno % n]
+        if re.search(regex, line):
+            if lineno - n >=3D stop and sep is not None and stop > 0:
+                yield sep
+            stop =3D lineno + n_after + 1
+        lines[lineno % n] =3D line
+        lineno +=3D 1
+
+    for i in range(max(lineno - n, 0), min(stop, lineno)):
+        yield lines[i % n]
=20
 register =3D template.Library()
=20
@@ -17,3 +68,29 @@ register =3D template.Library()
 @register.filter
 def ansi2text(value):
     return ''.join(logviewer.ansi2text(value))
+
+@register.simple_tag
+@register.filter
+def tail_lines(value, n):
+    lines =3D deque(lines_iter(value), n)
+    return '\n'.join(lines)
+
+@register.simple_tag
+@register.filter
+def grep(value, regex, sep=3DNone):
+    return '\n'.join(grep_iter(value, regex, 0, 0, sep))
+
+@register.simple_tag
+@register.filter
+def grep_A(value, regex, n=3D3, sep=3D'---'):
+    return '\n'.join(grep_iter(value, regex, 0, n, sep))
+
+@register.simple_tag
+@register.filter
+def grep_B(value, regex, n=3D3, sep=3D'---'):
+    return '\n'.join(grep_iter(value, regex, n, 0, sep))
+
+@register.simple_tag
+@register.filter
+def grep_C(value, regex, n=3D3, sep=3D'---'):
+    return '\n'.join(grep_iter(value, regex, n, n, sep))
diff --git a/tests/test_custom_tags.py b/tests/test_custom_tags.py
index ec875c8..aa828be 100755
--- a/tests/test_custom_tags.py
+++ b/tests/test_custom_tags.py
@@ -9,6 +9,7 @@
 # http://opensource.org/licenses/MIT.
=20
 from django.template import Context, Template
+from patchew.tags import tail_lines, grep_A, grep_B, grep_C, grep
 import patchewtest
 import unittest
=20
@@ -19,9 +20,110 @@ class CustomTagsTest(unittest.TestCase):
=20
     def test_template_filters(self):
         self.assertTemplate('{{s|ansi2text}}', 'dbc', s=3D'abc\rd')
+        self.assertTemplate('{{s|grep:"[0-9]"}}', '0\n9', s=3D'0\na\n9')
+        self.assertTemplate('{{s|grep_A:"b"}}',
+                            'b\nc\nd\ne\n---\nb',
+                             s=3D'a\nb\nc\nd\ne\nf\nx\ny\nz\nb')
+        self.assertTemplate('{{s|grep_B:"b"}}',
+                            'a\nb\n---\nx\ny\nz\nb',
+                             s=3D'a\nb\nc\nd\ne\nf\nx\ny\nz\nb')
+        self.assertTemplate('{{s|grep_C:"b"}}',
+                            'a\nb\nc\nd\ne\n---\nx\ny\nz\nb',
+                             s=3D'a\nb\nc\nd\ne\nf\nx\ny\nz\nb')
+        self.assertTemplate('{{s|tail_lines:3}}', 'b\nc\nd', s=3D'a\nb\nc\=
nd')
=20
     def test_template_tags(self):
         self.assertTemplate('{% ansi2text s %}', 'dbc', s=3D'abc\rd')
+        self.assertTemplate('{% grep s "[0-9]" %}', '0\n9', s=3D'0\na\n9')
+        self.assertTemplate('{% grep_A s regex=3D"[bc]" n=3D1 %}', 'b\nc\n=
d', s=3D'a\nb\nc\nd')
+        self.assertTemplate('{% grep_B s regex=3D"[bc]" n=3D1 %}', 'a\nb\n=
c', s=3D'a\nb\nc\nd')
+        self.assertTemplate('{% grep_C s "b" n=3D1 %}', 'a\nb\nc', s=3D'a\=
nb\nc\nd')
+        self.assertTemplate('{% tail_lines s n=3D3 %}', 'b\nc\nd', s=3D'a\=
nb\nc\nd')
+
+    def test_grep(self):
+        self.assertEqual(grep('0\na\n9', '[0-9]'), '0\n9')
+        self.assertEqual(grep('0\na\n9', '[0-9]', '---'), '0\n---\n9')
+
+    def test_grep_A(self):
+        self.assertEqual(grep_A('a\nb\nc\nd', 'b', 1, None), 'b\nc')
+        self.assertEqual(grep_A('a\nb\nc\nd', 'b', 2, None), 'b\nc\nd')
+        self.assertEqual(grep_A('a\nb\nc\nd\nb\ne', 'b', 1, None), 'b\nc\n=
b\ne')
+        self.assertEqual(grep_A('a\nb\nc\nd\nb\ne', 'b', 2, None), 'b\nc\n=
d\nb\ne')
+        self.assertEqual(grep_A('a\nb\nc\nd\nz\nb\ne', 'b', 1, None), 'b\n=
c\nb\ne')
+        self.assertEqual(grep_A('a\nb\nc\nd\nz\nb\ne', 'b', 2, None), 'b\n=
c\nd\nb\ne')
+        self.assertEqual(grep_A('a\nb\nc\nz\nb\nb\ne', 'b', 1, None), 'b\n=
c\nb\nb\ne')
+        self.assertEqual(grep_A('b\nc\nz\nb\nb\ne', 'b', 1, None), 'b\nc\n=
b\nb\ne')
+        self.assertEqual(grep_A('b\n', 'b', 1, None), 'b')
+
+    def test_grep_A_sep(self):
+        self.assertEqual(grep_A('a\nb\nc\nd', 'b', 1), 'b\nc')
+        self.assertEqual(grep_A('a\nb\nc\nd', 'b', 2), 'b\nc\nd')
+        self.assertEqual(grep_A('a\nb\nc\nd\nb\ne', 'b', 1), 'b\nc\n---\nb=
\ne')
+        self.assertEqual(grep_A('a\nb\nc\nd\nb\ne', 'b', 2), 'b\nc\nd\nb\n=
e')
+        self.assertEqual(grep_A('a\nb\nc\nd\nz\nb\ne', 'b', 1), 'b\nc\n---=
\nb\ne')
+        self.assertEqual(grep_A('a\nb\nc\nd\nz\nb\nb\ne', 'b', 1), 'b\nc\n=
---\nb\nb\ne')
+        self.assertEqual(grep_A('b\nc\nz\nb\nb\ne', 'b', 1), 'b\nc\n---\nb=
\nb\ne')
+        self.assertEqual(grep_A('b\n', 'b', 1), 'b')
+
+    def test_grep_B(self):
+        self.assertEqual(grep_B('a\nb\nc\nd', 'b', 1, None), 'a\nb')
+        self.assertEqual(grep_B('a\nb\nc\nd', 'b', 2, None), 'a\nb')
+        self.assertEqual(grep_B('a\nb\nc\nd\nb\ne', 'b', 1, None), 'a\nb\n=
d\nb')
+        self.assertEqual(grep_B('a\nb\nc\nd\nz\nb\ne', 'b', 1, None), 'a\n=
b\nz\nb')
+        self.assertEqual(grep_B('a\nb\nc\nd\nz\nb\ne', 'b', 2, None), 'a\n=
b\nd\nz\nb')
+        self.assertEqual(grep_B('a\nb\nc\nz\nb\nb\ne', 'b', 1, None), 'a\n=
b\nz\nb\nb')
+        self.assertEqual(grep_B('b\nc\nz\nb\nb\ne', 'b', 1, None), 'b\nz\n=
b\nb')
+        self.assertEqual(grep_B('b\n', 'b', 1, None), 'b')
+
+    def test_grep_B_sep(self):
+        self.assertEqual(grep_B('a\nb\nc\nd', 'b', 1), 'a\nb')
+        self.assertEqual(grep_B('a\nb\nc\nd', 'b', 2), 'a\nb')
+        self.assertEqual(grep_B('a\nb\nc\nd\nb\ne', 'b', 1), 'a\nb\n---\nd=
\nb')
+        self.assertEqual(grep_B('a\nb\nc\nd\nz\nb\ne', 'b', 1), 'a\nb\n---=
\nz\nb')
+        self.assertEqual(grep_B('a\nb\nc\nd\nz\nb\ne', 'b', 2), 'a\nb\n---=
\nd\nz\nb')
+        self.assertEqual(grep_B('a\nb\nc\nz\nb\nb\ne', 'b', 1), 'a\nb\n---=
\nz\nb\nb')
+        self.assertEqual(grep_B('b\nc\nz\nb\nb\ne', 'b', 1), 'b\n---\nz\nb=
\nb')
+        self.assertEqual(grep_B('b\n', 'b', 1), 'b')
+
+    def test_grep_C(self):
+        self.assertEqual(grep_C('a\nb\nc\nd', 'b', 1, None), 'a\nb\nc')
+        self.assertEqual(grep_C('a\nb\nc\nd', 'b', 2, None), 'a\nb\nc\nd')
+        self.assertEqual(grep_C('a\nb\nc\nd\nb\ne', 'b', 1, None), 'a\nb\n=
c\nd\nb\ne')
+        self.assertEqual(grep_C('a\nb\nc\nd\nz\nb\ne', 'b', 1, None), 'a\n=
b\nc\nz\nb\ne')
+        self.assertEqual(grep_C('a\nb\nc\nd\nz\nb\ne', 'b', 2, None), 'a\n=
b\nc\nd\nz\nb\ne')
+        self.assertEqual(grep_C('a\nb\nc\nz\nb\nb\ne', 'b', 1, None), 'a\n=
b\nc\nz\nb\nb\ne')
+        self.assertEqual(grep_C('b\nc\nz\nb\nb\ne', 'b', 1, None), 'b\nc\n=
z\nb\nb\ne')
+        self.assertEqual(grep_C('b\n', 'b', 1, None), 'b')
+
+    def test_grep_C_sep(self):
+        self.assertEqual(grep_C('a\nb\nc\nd', 'b', 1), 'a\nb\nc')
+        self.assertEqual(grep_C('a\nb\nc\nd', 'b', 2), 'a\nb\nc\nd')
+        self.assertEqual(grep_C('a\nb\nc\nd\nb\ne', 'b', 1), 'a\nb\nc\nd\n=
b\ne')
+        self.assertEqual(grep_C('a\nb\nc\nd\nz\nb\ne', 'b', 1), 'a\nb\nc\n=
---\nz\nb\ne')
+        self.assertEqual(grep_C('a\nb\nc\nd\nz\nb\ne', 'b', 2), 'a\nb\nc\n=
d\nz\nb\ne')
+        self.assertEqual(grep_C('a\nb\nc\nz\nb\nb\ne', 'b', 1), 'a\nb\nc\n=
z\nb\nb\ne')
+        self.assertEqual(grep_C('b\nc\nz\nb\nb\ne', 'b', 1), 'b\nc\nz\nb\n=
b\ne')
+        self.assertEqual(grep_C('b\n', 'b', 1), 'b')
+
+    def test_tail_lines(self):
+        self.assertEqual(tail_lines('', 0), '')
+        self.assertEqual(tail_lines('', 1), '')
+        self.assertEqual(tail_lines('', 2), '')
+        self.assertEqual(tail_lines('', 4), '')
+
+        self.assertEqual(tail_lines('a\nb\n', 0), '')
+        self.assertEqual(tail_lines('a\nb\n', 1), 'b')
+        self.assertEqual(tail_lines('a\nb\n', 2), 'a\nb')
+
+        self.assertEqual(tail_lines('a\nb\nc\n', 2), 'b\nc')
+        self.assertEqual(tail_lines('a\nb\nc\n', 4), 'a\nb\nc')
+
+        self.assertEqual(tail_lines('a\nb\nc\nd\n', 2), 'c\nd')
+
+        self.assertEqual(tail_lines('\n\n\n', 2), '\n')
+        self.assertEqual(tail_lines('\n\n\nbc', 2), '\nbc')
+        self.assertEqual(tail_lines('\n\nbc', 3), '\n\nbc')
+        self.assertEqual(tail_lines('\n\n\n\nbc', 3), '\n\nbc')
=20
 if __name__ =3D=3D '__main__':
     unittest.main()
--=20
2.14.3



From nobody Thu May  2 15:14:31 2024
Delivered-To: importer@patchew.org
Received-SPF: none (zoho.com: 206.53.239.180 is neither permitted nor denied
 by domain of freelists.org) client-ip=206.53.239.180;
 envelope-from=patchew-devel-bounce@freelists.org; helo=turing.freelists.org;
Authentication-Results: mx.zohomail.com;
	dkim=pass;
	spf=none (zoho.com: 206.53.239.180 is neither permitted nor denied by domain
 of freelists.org)  smtp.mailfrom=patchew-devel-bounce@freelists.org;
	dmarc=fail(p=none dis=none)  header.from=redhat.com
Return-Path: 
Received: from turing.freelists.org (turing.freelists.org [206.53.239.180]) by
 mx.zohomail.com
	with SMTPS id 1520241403110115.59299665404626;
 Mon, 5 Mar 2018 01:16:43 -0800 (PST)
Received: from localhost (localhost [127.0.0.1])
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id
 910DA272B4;
	Mon,  5 Mar 2018 04:16:42 -0500 (EST)
Received: from turing.freelists.org ([127.0.0.1])
	by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024)
	with ESMTP id V2SbLpPxNlML; Mon,  5 Mar 2018 04:16:42 -0500 (EST)
Received: from turing.freelists.org (localhost [127.0.0.1])
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id
 45F2226402;
	Mon,  5 Mar 2018 04:16:42 -0500 (EST)
Received: with ECARTIS (v1.0.0; list patchew-devel);
 Mon, 05 Mar 2018 04:16:42 -0500 (EST)
Received: from localhost (localhost [127.0.0.1])
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id
 1202E272B4
	for ; Mon,  5 Mar 2018 04:16:42 -0500 (EST)
Received: from turing.freelists.org ([127.0.0.1])
	by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024)
	with ESMTP id auSPn4wZKysV for ;
	Mon,  5 Mar 2018 04:16:42 -0500 (EST)
Received: from mail-wr0-f196.google.com (mail-wr0-f196.google.com
 [209.85.128.196])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id
 A1D1926402
	for ; Mon,  5 Mar 2018 04:16:41 -0500 (EST)
Received: by mail-wr0-f196.google.com with SMTP id v111so16404269wrb.3
        for ;
 Mon, 05 Mar 2018 01:16:41 -0800 (PST)
Received: from donizetti.lan (94-36-191-219.adsl-ull.clienti.tiscali.it.
 [94.36.191.219])
        by smtp.gmail.com with ESMTPSA id
 b68sm7018546wmi.30.2018.03.05.01.16.38
        for 
        (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256);
        Mon, 05 Mar 2018 01:16:38 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=freelists.org;
	s=turing; t=1520241402;
	bh=Tt9L8lG7YcBoqGyo8Cv82Mvlz9exrdPCwBWbjIydAxw=;
	h=From:To:Subject:Date:In-Reply-To:References:Reply-To:List-help:
	 List-unsubscribe:List-Id:List-subscribe:List-owner:List-post:
	 List-archive;
	b=k/dIQZCmmOKv3BlOcORSUBM97hOhBb6xM2MObiZ8bfVKRNT+xoaT2FNRX7QF5k4/Q
	 D8N2achxy3lK9K8uxocusr5NQvv4IALNS7Qd3nasjpaaBSm+FWr+389INf46CjZpeB
	 TD0CFckGq2AUb8v9RrFwV9GFFK8I0gvk2oEw0L+I=
X-Virus-Scanned: Debian amavisd-new at turing.freelists.org
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=freelists.org;
	s=turing; t=1520241402;
	bh=Tt9L8lG7YcBoqGyo8Cv82Mvlz9exrdPCwBWbjIydAxw=;
	h=From:To:Subject:Date:In-Reply-To:References:Reply-To:List-help:
	 List-unsubscribe:List-Id:List-subscribe:List-owner:List-post:
	 List-archive;
	b=k/dIQZCmmOKv3BlOcORSUBM97hOhBb6xM2MObiZ8bfVKRNT+xoaT2FNRX7QF5k4/Q
	 D8N2achxy3lK9K8uxocusr5NQvv4IALNS7Qd3nasjpaaBSm+FWr+389INf46CjZpeB
	 TD0CFckGq2AUb8v9RrFwV9GFFK8I0gvk2oEw0L+I=
X-Original-To: patchew-devel@freelists.org
X-Virus-Scanned: Debian amavisd-new at turing.freelists.org
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:sender:from:to:subject:date:message-id
         :in-reply-to:references;
        bh=6SS+eRxV+FjaSJ+Z5pyY0IIgQ5JkKuYDd0OYA/PjVBQ=;
        b=dSxBVhXN94g6EANaiFB1/1Qp2aZ9Ux8GwMqLC48/Qslx2nud4MviwfYPFQB5exaAOj
         fNdcWKgYsHVUfU2fUw166QMaQrrzUGT+NtKrJu5NTReBByFf+mLnRiyxeYg6ZQkAKta8
         qUwsWSmjeuBBguRqojzjnC65Ou7ZWFsF6CrOTly7OLGwFocIu6QyquslXPA37Z20OmSM
         md0ioWZPzuWZiEw3DG9K4gdZW7VpvcneXQkXiRTVeUqX23qHcmCoTW/3982EnXyJRNbz
         hlGYr/lkcnobjwiR3NwHSg63ktv5XmNtyzheVosKlHTOV1I9qpdpEcCk9Xrr/4FKxLCS
         LSRA==
X-Gm-Message-State: APf1xPAA2YqrzvkQ9m3c0x7c8PTKcK82drT0t1THb11brTemjdGEVT1i
	aEuyeSyDrdFqFiTzXGK4ptombs4a
X-Google-Smtp-Source: 
 AG47ELtm+GqohTltMyeJCnM0ZUEka4TTKq3wm/ZU3jGZftPFAmwseuf+Fl3YkVRuRnwkMIlbyVU8tQ==
X-Received: by 10.223.169.161 with SMTP id b30mr13228655wrd.232.1520241399798;
        Mon, 05 Mar 2018 01:16:39 -0800 (PST)
From: Paolo Bonzini 
To: patchew-devel@freelists.org
Subject: [patchew-devel] [PATCH 5/6] testing: add reverse_testing_log
Date: Mon,  5 Mar 2018 10:16:33 +0100
Message-Id: <20180305091634.7391-6-pbonzini@redhat.com>
X-Mailer: git-send-email 2.14.3
In-Reply-To: <20180305091634.7391-1-pbonzini@redhat.com>
References: <20180305091634.7391-1-pbonzini@redhat.com>
X-archive-position: 77
X-ecartis-version: Ecartis v1.0.0
Sender: patchew-devel-bounce@freelists.org
Errors-to: patchew-devel-bounce@freelists.org
X-original-sender: pbonzini@redhat.com
Precedence: normal
Reply-To: patchew-devel@freelists.org
List-help: 
List-unsubscribe: 
List-software: Ecartis version 1.0.0
List-Id: patchew-devel 
X-List-ID: patchew-devel 
List-subscribe: 
List-owner: 
List-post: 
List-archive: 
X-list: patchew-devel
X-ZohoMail-DKIM: pass (identity @freelists.org)
X-ZohoMail: RDKM_0  RSF_4  Z_629925259 SPT_0
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"

Abstract the creation of testing log URLs.

Signed-off-by: Paolo Bonzini 
---
 mods/testing.py | 41 +++++++++++++++++++++--------------------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/mods/testing.py b/mods/testing.py
index 47933e2..7125d58 100644
--- a/mods/testing.py
+++ b/mods/testing.py
@@ -146,6 +146,24 @@ class TestingModule(PatchewModule):
                                TestingLogViewer.as_view(),
                                name=3D"testing-log"))
=20
+    def reverse_testing_log(self, obj, test, request=3DNone, html=3DFalse):
+        if isinstance(obj, Message):
+            log_url =3D reverse("testing-log",
+                              kwargs=3D{"project_or_series": obj.message_i=
d,
+                                      "testing_name": test}) + "?type=3Dme=
ssage"
+        else:
+            assert(isinstance(obj, Project))
+            log_url =3D reverse.reverse("testing-log",
+                              kwargs=3D{"project_or_series": obj.name,
+                                      "testing_name": test}) + "?type=3Dpr=
oject"
+        if html:
+            log_url +=3D "&html=3D1"
+        # Generate a full URL, including the host and port, for use in ema=
il
+        # notifications and REST API responses.
+        if request:
+            log_url =3D request.build_absolute_uri(url)
+        return log_url
+
     def add_test_report(self, user, project, tester, test, head,
                         base, identity, passed, log, is_timeout):
         # Find a project or series depending on the test type and assign i=
t to obj
@@ -203,20 +221,8 @@ class TestingModule(PatchewModule):
                 continue
             tn =3D pn[len("testing.report."):]
             failed =3D not p["passed"]
-            log_prop =3D "testing.log." + tn
-            if isinstance(obj, Message):
-                typearg =3D "type=3Dmessage"
-                log_url =3D reverse("testing-log",
-                                  kwargs=3D{"project_or_series": obj.messa=
ge_id,
-                                          "testing_name": tn})
-            else:
-                assert(isinstance(obj, Project))
-                typearg =3D "type=3Dproject"
-                log_url =3D reverse("testing-log",
-                                  kwargs=3D{"project_or_series": obj.name,
-                                          "testing_name": tn})
-            log_url +=3D "?" + typearg
-            html_log_url =3D log_url + "&html=3D1"
+            log_url =3D self.reverse_testing_log(obj, tn, html=3DFalse)
+            html_log_url =3D self.reverse_testing_log(obj, tn, html=3DTrue)
             passed_str =3D "failed" if failed else "passed"
             html =3D format_html('Test {} {}',
                                tn, html_log_url, log_url, passed_str)
@@ -263,12 +269,7 @@ class TestingModule(PatchewModule):
                 continue
             tn =3D pn[len("testing.report."):]
             failed =3D not p["passed"]
-            log_prop =3D "testing.log." + tn
-            typearg =3D "type=3Dmessage"
-            log_url =3D reverse("testing-log",
-                              kwargs=3D{"project_or_series": message.messa=
ge_id,
-                                      "testing_name": tn})
-            log_url +=3D "?" + typearg
+            log_url =3D self.reverse_testing_log(message, tn, request=3Dre=
quest, html=3DFalse)
             passed_str =3D "failure" if failed else "success"
             result =3D {
                 'status': passed_str,
--=20
2.14.3



From nobody Thu May  2 15:14:31 2024
Delivered-To: importer@patchew.org
Received-SPF: none (zoho.com: 206.53.239.180 is neither permitted nor denied
 by domain of freelists.org) client-ip=206.53.239.180;
 envelope-from=patchew-devel-bounce@freelists.org; helo=turing.freelists.org;
Authentication-Results: mx.zohomail.com;
	dkim=pass;
	spf=none (zoho.com: 206.53.239.180 is neither permitted nor denied by domain
 of freelists.org)  smtp.mailfrom=patchew-devel-bounce@freelists.org;
	dmarc=fail(p=none dis=none)  header.from=redhat.com
Return-Path: 
Received: from turing.freelists.org (turing.freelists.org [206.53.239.180]) by
 mx.zohomail.com
	with SMTPS id 1520241403827782.6262065983689;
 Mon, 5 Mar 2018 01:16:43 -0800 (PST)
Received: from localhost (localhost [127.0.0.1])
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id
 4548D26402;
	Mon,  5 Mar 2018 04:16:43 -0500 (EST)
Received: from turing.freelists.org ([127.0.0.1])
	by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024)
	with ESMTP id V_KXTspFQDtH; Mon,  5 Mar 2018 04:16:43 -0500 (EST)
Received: from turing.freelists.org (localhost [127.0.0.1])
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id
 EEE95272BB;
	Mon,  5 Mar 2018 04:16:42 -0500 (EST)
Received: with ECARTIS (v1.0.0; list patchew-devel);
 Mon, 05 Mar 2018 04:16:42 -0500 (EST)
Received: from localhost (localhost [127.0.0.1])
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id
 BB62C26402
	for ; Mon,  5 Mar 2018 04:16:42 -0500 (EST)
Received: from turing.freelists.org ([127.0.0.1])
	by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024)
	with ESMTP id Y1ibtvvd5mQW for ;
	Mon,  5 Mar 2018 04:16:42 -0500 (EST)
Received: from mail-wm0-f68.google.com (mail-wm0-f68.google.com
 [74.125.82.68])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id
 66904272BB
	for ; Mon,  5 Mar 2018 04:16:42 -0500 (EST)
Received: by mail-wm0-f68.google.com with SMTP id h21so14292578wmd.1
        for ;
 Mon, 05 Mar 2018 01:16:42 -0800 (PST)
Received: from donizetti.lan (94-36-191-219.adsl-ull.clienti.tiscali.it.
 [94.36.191.219])
        by smtp.gmail.com with ESMTPSA id
 b68sm7018546wmi.30.2018.03.05.01.16.39
        for 
        (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256);
        Mon, 05 Mar 2018 01:16:40 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=freelists.org;
	s=turing; t=1520241403;
	bh=bzK6TLntIYAc6Yp1ADCDFG+MCYwod8zUHRhJ6NRnm78=;
	h=From:To:Subject:Date:In-Reply-To:References:Reply-To:List-help:
	 List-unsubscribe:List-Id:List-subscribe:List-owner:List-post:
	 List-archive;
	b=g0Cs/pso0mOxfEUVR9/8R9qeJ+cD0IcsfDadYypZJaPwG3QjG6kXr3fUE4xpm4w9F
	 8YdLtBsAdC6YMZ8qwG5mLOI6GakgzoTB1yRMNH5kMBAPcMPN+r+cUrClMXxJyh5LrO
	 kKBHBaFrqxHxNixfGz6//YxgqNXOTb8tcvIrFcMM=
X-Virus-Scanned: Debian amavisd-new at turing.freelists.org
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=freelists.org;
	s=turing; t=1520241403;
	bh=bzK6TLntIYAc6Yp1ADCDFG+MCYwod8zUHRhJ6NRnm78=;
	h=From:To:Subject:Date:In-Reply-To:References:Reply-To:List-help:
	 List-unsubscribe:List-Id:List-subscribe:List-owner:List-post:
	 List-archive;
	b=g0Cs/pso0mOxfEUVR9/8R9qeJ+cD0IcsfDadYypZJaPwG3QjG6kXr3fUE4xpm4w9F
	 8YdLtBsAdC6YMZ8qwG5mLOI6GakgzoTB1yRMNH5kMBAPcMPN+r+cUrClMXxJyh5LrO
	 kKBHBaFrqxHxNixfGz6//YxgqNXOTb8tcvIrFcMM=
X-Original-To: patchew-devel@freelists.org
X-Virus-Scanned: Debian amavisd-new at turing.freelists.org
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:sender:from:to:subject:date:message-id
         :in-reply-to:references;
        bh=kWjYfW5C7P2LO4YK482imtg+qlpUAJFNDT+VyQm+jsE=;
        b=B83QnsIULXfxi6W8DDgEk8gXyZkxDrghRQAmg6A/HupgkOlzaupYYW+a4b809KUc6v
         bZBU0bPH3VTHFHrRTfGDySyCQWWOhxJoiZQ3asPi3ikksfy0285pEuP5hQzyGjhE5K5P
         yvAwWWXdpOxKdpCLZAyk3I14wXwe9Kpq3TIz9en4xZhDjZ75gCO1tlrRP5fdMP0D94D/
         lTuTXDZECM4+mH+/ZjXMm1V4spUlGmNcnfUg06QMCFGacG3QNpkBnaqRyOKDX9YMFf++
         y5F+RPXxgzoXBwBr76LSNKq17IH9aUjul9YDoLCjITE8+YvFQlULwLPZkobizmzT2dMy
         mRrw==
X-Gm-Message-State: AElRT7GXCUlJAE9f+boH5knYz6AtQ2tktaA5I6pzLSCUyOHDgApNH5Am
	zyNDFNjKaSTawIzk2isac7XkAC+n
X-Google-Smtp-Source: 
 AG47ELunL2vZkd5D6MDJOhwYt+5SkhKz1zmhdYGevUwenpxLR0fTyXcFBYQzS465gY6CHlMXHtuqHQ==
X-Received: by 10.28.5.145 with SMTP id 139mr7125343wmf.89.1520241401122;
        Mon, 05 Mar 2018 01:16:41 -0800 (PST)
From: Paolo Bonzini 
To: patchew-devel@freelists.org
Subject: [patchew-devel] [PATCH 6/6] testing: pass log URL in the
 TestingReport event
Date: Mon,  5 Mar 2018 10:16:34 +0100
Message-Id: <20180305091634.7391-7-pbonzini@redhat.com>
X-Mailer: git-send-email 2.14.3
In-Reply-To: <20180305091634.7391-1-pbonzini@redhat.com>
References: <20180305091634.7391-1-pbonzini@redhat.com>
X-archive-position: 78
X-ecartis-version: Ecartis v1.0.0
Sender: patchew-devel-bounce@freelists.org
Errors-to: patchew-devel-bounce@freelists.org
X-original-sender: pbonzini@redhat.com
Precedence: normal
Reply-To: patchew-devel@freelists.org
List-help: 
List-unsubscribe: 
List-software: Ecartis version 1.0.0
List-Id: patchew-devel 
X-List-ID: patchew-devel 
List-subscribe: 
List-owner: 
List-post: 
List-archive: 
X-list: patchew-devel
X-ZohoMail-DKIM: pass (identity @freelists.org)
X-ZohoMail: RDKM_0  RSF_4  Z_629925259 SPT_0
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"

Signed-off-by: Paolo Bonzini 
---
 mods/testing.py | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/mods/testing.py b/mods/testing.py
index 7125d58..d075cf4 100644
--- a/mods/testing.py
+++ b/mods/testing.py
@@ -164,20 +164,21 @@ class TestingModule(PatchewModule):
             log_url =3D request.build_absolute_uri(url)
         return log_url
=20
-    def add_test_report(self, user, project, tester, test, head,
+    def add_test_report(self, request, project, tester, test, head,
                         base, identity, passed, log, is_timeout):
         # Find a project or series depending on the test type and assign i=
t to obj
         if identity["type"] =3D=3D "project":
             obj =3D Project.objects.get(name=3Dproject)
-            is_proj_report =3D True
             project =3D obj.name
         elif identity["type"] =3D=3D "series":
             message_id =3D identity["message-id"]
             obj =3D Message.objects.find_series(message_id, project)
             if not obj:
                 raise Exception("Series doesn't exist")
-            is_proj_report =3D False
             project =3D obj.project.name
+        user =3D request.user
+        log_url =3D self.reverse_testing_log(obj, test, request=3Drequest)
+        html_log_url =3D self.reverse_testing_log(obj, test, request=3Dreq=
uest, html=3DTrue)
         obj.set_property("testing.report." + test,
                          {"passed": passed,
                           "is_timeout": is_timeout,
@@ -195,8 +196,8 @@ class TestingModule(PatchewModule):
         if all_tests.issubset(done_tests):
             obj.set_property("testing.tested-head", head)
         emit_event("TestingReport", tester=3Dtester, user=3Duser.username,
-                    obj=3Dobj, passed=3Dpassed, test=3Dtest, log=3Dlog,
-                    is_timeout=3Dis_timeout)
+                    obj=3Dobj, passed=3Dpassed, test=3Dtest, log=3Dlog, lo=
g_url=3Dlog_url,
+                    html_log_url=3Dhtml_log_url, is_timeout=3Dis_timeout)
=20
     def get_tests(self, obj):
         ret =3D {}
@@ -475,7 +476,7 @@ class TestingReportView(APILoginRequiredView):
                head, base, passed, log, identity,
                is_timeout=3DFalse):
         _instance.tester_check_in(project, tester or request.user.username)
-        _instance.add_test_report(request.user, project, tester,
+        _instance.add_test_report(request, project, tester,
                                   test, head, base, identity, passed, log,
                                   is_timeout)
=20
--=20
2.14.3