public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Tom Rini <trini@konsulko.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [RFC v2 4/10] test/py: Automated conversion to Python 3
Date: Sat, 19 Oct 2019 07:22:57 -0400	[thread overview]
Message-ID: <20191019112257.GA11173@bill-the-cat> (raw)
In-Reply-To: <20191019061318.16029-1-xypron.glpk@gmx.de>

On Sat, Oct 19, 2019 at 08:13:18AM +0200, Heinrich Schuchardt wrote:
> From: Tom Rini <trini@konsulko.com>
> 
> Use the 2to3 tool to perform numerous automatic conversions from Python
> 2 syntax to Python 3.  Also fix whitespace problems that Python 3
> catches that Python 2 did not.
> 
> Signed-off-by: Tom Rini <trini@konsulko.com>
> 
> Add missing Python 3 conversion.
> 
> Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

Thanks!  I'll slightly reword the commit message and pick this part up.

> ---
>  test/py/conftest.py               |  9 ++--
>  test/py/multiplexed_log.py        |  4 +-
>  test/py/test.py                   |  4 +-
>  test/py/tests/test_fit.py         | 12 +++--
>  test/py/tests/test_fpga.py        | 46 +++++++++----------
>  test/py/tests/test_fs/conftest.py |  4 +-
>  test/py/tests/test_log.py         |  8 ++--
>  test/py/tests/test_mmc_wr.py      | 74 +++++++++++++++----------------
>  8 files changed, 76 insertions(+), 85 deletions(-)
> 
> diff --git a/test/py/conftest.py b/test/py/conftest.py
> index 30c898b40a..7da4b77bce 100644
> --- a/test/py/conftest.py
> +++ b/test/py/conftest.py
> @@ -19,13 +19,10 @@ import os.path
>  import pytest
>  from _pytest.runner import runtestprotocol
>  import re
> -import StringIO
> +import io
>  import sys
> 
> -try:
> -    import configparser
> -except:
> -    import ConfigParser as configparser
> +import configparser
> 
>  # Globals: The HTML log file, and the connection to the U-Boot console.
>  log = None
> @@ -169,7 +166,7 @@ def pytest_configure(config):
> 
>          with open(dot_config, 'rt') as f:
>              ini_str = '[root]\n' + f.read()
> -            ini_sio = StringIO.StringIO(ini_str)
> +            ini_sio = io.StringIO(ini_str.decode())
>              parser = configparser.RawConfigParser()
>              parser.readfp(ini_sio)
>              ubconfig.buildconfig.update(parser.items('root'))
> diff --git a/test/py/multiplexed_log.py b/test/py/multiplexed_log.py
> index 637a3bd257..de0aacc659 100644
> --- a/test/py/multiplexed_log.py
> +++ b/test/py/multiplexed_log.py
> @@ -5,8 +5,8 @@
>  # Generate an HTML-formatted log file containing multiple streams of data,
>  # each represented in a well-delineated/-structured fashion.
> 
> -import cgi
>  import datetime
> +import html
>  import os.path
>  import shutil
>  import subprocess
> @@ -334,7 +334,7 @@ $(document).ready(function () {
>          data = data.replace(chr(13), '')
>          data = ''.join((ord(c) in self._nonprint) and ('%%%02x' % ord(c)) or
>                         c for c in data)
> -        data = cgi.escape(data)
> +        data = html.escape(data)
>          return data
> 
>      def _terminate_stream(self):
> diff --git a/test/py/test.py b/test/py/test.py
> index a5140945d4..0ce1838833 100755
> --- a/test/py/test.py
> +++ b/test/py/test.py
> @@ -1,4 +1,4 @@
> -#!/usr/bin/env python2
> +#!/usr/bin/env python3
>  # SPDX-License-Identifier: GPL-2.0
> 
>  # Copyright (c) 2015 Stephen Warren
> @@ -7,8 +7,6 @@
>  # Wrapper script to invoke pytest with the directory name that contains the
>  # U-Boot tests.
> 
> -from __future__ import print_function
> -
>  import os
>  import os.path
>  import sys
> diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py
> index e3210ed43f..ea9286a553 100755
> --- a/test/py/tests/test_fit.py
> +++ b/test/py/tests/test_fit.py
> @@ -3,8 +3,6 @@
>  #
>  # Sanity check of the FIT handling in U-Boot
> 
> -from __future__ import print_function
> -
>  import os
>  import pytest
>  import struct
> @@ -155,7 +153,7 @@ def test_fit(u_boot_console):
>          src = make_fname('u-boot.dts')
>          dtb = make_fname('u-boot.dtb')
>          with open(src, 'w') as fd:
> -            print(base_fdt, file=fd)
> +            fd.write(base_fdt)
>          util.run_and_log(cons, ['dtc', src, '-O', 'dtb', '-o', dtb])
>          return dtb
> 
> @@ -169,7 +167,7 @@ def test_fit(u_boot_console):
>          """
>          its = make_fname('test.its')
>          with open(its, 'w') as fd:
> -            print(base_its % params, file=fd)
> +            fd.write(base_its % params)
>          return its
> 
>      def make_fit(mkimage, params):
> @@ -188,7 +186,7 @@ def test_fit(u_boot_console):
>          its = make_its(params)
>          util.run_and_log(cons, [mkimage, '-f', its, fit])
>          with open(make_fname('u-boot.dts'), 'w') as fd:
> -            print(base_fdt, file=fd)
> +            fd.write(base_fdt)
>          return fit
> 
>      def make_kernel(filename, text):
> @@ -204,7 +202,7 @@ def test_fit(u_boot_console):
>          for i in range(100):
>              data += 'this %s %d is unlikely to boot\n' % (text, i)
>          with open(fname, 'w') as fd:
> -            print(data, file=fd)
> +            fd.write(data)
>          return fname
> 
>      def make_ramdisk(filename, text):
> @@ -218,7 +216,7 @@ def test_fit(u_boot_console):
>          for i in range(100):
>              data += '%s %d was seldom used in the middle ages\n' % (text, i)
>          with open(fname, 'w') as fd:
> -            print(data, file=fd)
> +            fd.write(data)
>          return fname
> 
>      def make_compressed(filename):
> diff --git a/test/py/tests/test_fpga.py b/test/py/tests/test_fpga.py
> index e3bb7b41c7..ca7ef8ea40 100644
> --- a/test/py/tests/test_fpga.py
> +++ b/test/py/tests/test_fpga.py
> @@ -175,29 +175,29 @@ def test_fpga_load_fail(u_boot_console):
>      f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_load')
> 
>      for cmd in ['dump', 'load', 'loadb']:
> -	# missing dev parameter
> -	expected = 'fpga: incorrect parameters passed'
> -	output = u_boot_console.run_command('fpga %s %x $filesize' % (cmd, addr))
> -	#assert expected in output
> -	assert expected_usage in output
> -
> -	# more parameters - 0 at the end
> -	expected = 'fpga: more parameters passed'
> -	output = u_boot_console.run_command('fpga %s %x %x $filesize 0' % (cmd, dev, addr))
> -	#assert expected in output
> -	assert expected_usage in output
> -
> -	# 0 address
> -	expected = 'fpga: zero fpga_data address'
> -	output = u_boot_console.run_command('fpga %s %x 0 $filesize' % (cmd, dev))
> -	#assert expected in output
> -	assert expected_usage in output
> -
> -	# 0 filesize
> -	expected = 'fpga: zero size'
> -	output = u_boot_console.run_command('fpga %s %x %x 0' % (cmd, dev, addr))
> -	#assert expected in output
> -	assert expected_usage in output
> +        # missing dev parameter
> +        expected = 'fpga: incorrect parameters passed'
> +        output = u_boot_console.run_command('fpga %s %x $filesize' % (cmd, addr))
> +        #assert expected in output
> +        assert expected_usage in output
> +
> +        # more parameters - 0 at the end
> +        expected = 'fpga: more parameters passed'
> +        output = u_boot_console.run_command('fpga %s %x %x $filesize 0' % (cmd, dev, addr))
> +        #assert expected in output
> +        assert expected_usage in output
> +
> +        # 0 address
> +        expected = 'fpga: zero fpga_data address'
> +        output = u_boot_console.run_command('fpga %s %x 0 $filesize' % (cmd, dev))
> +        #assert expected in output
> +        assert expected_usage in output
> +
> +        # 0 filesize
> +        expected = 'fpga: zero size'
> +        output = u_boot_console.run_command('fpga %s %x %x 0' % (cmd, dev, addr))
> +        #assert expected in output
> +        assert expected_usage in output
> 
>  @pytest.mark.buildconfigspec('cmd_fpga')
>  @pytest.mark.buildconfigspec('cmd_echo')
> diff --git a/test/py/tests/test_fs/conftest.py b/test/py/tests/test_fs/conftest.py
> index 9324657d21..354d17672f 100644
> --- a/test/py/tests/test_fs/conftest.py
> +++ b/test/py/tests/test_fs/conftest.py
> @@ -508,8 +508,8 @@ def fs_obj_unlink(request, u_boot_config):
> 
>          # Test Case 2
>          check_call('mkdir %s/dir2' % mount_dir, shell=True)
> -	for i in range(0, 20):
> -	    check_call('mkdir %s/dir2/0123456789abcdef%02x'
> +        for i in range(0, 20):
> +            check_call('mkdir %s/dir2/0123456789abcdef%02x'
>                                      % (mount_dir, i), shell=True)
> 
>          # Test Case 4
> diff --git a/test/py/tests/test_log.py b/test/py/tests/test_log.py
> index cb183444c6..75325fad61 100644
> --- a/test/py/tests/test_log.py
> +++ b/test/py/tests/test_log.py
> @@ -27,9 +27,9 @@ def test_log(u_boot_console):
>          """
>          for i in range(max_level):
>              if mask & 1:
> -                assert 'log_run() log %d' % i == lines.next()
> +                assert 'log_run() log %d' % i == next(lines)
>              if mask & 3:
> -                assert 'func() _log %d' % i == lines.next()
> +                assert 'func() _log %d' % i == next(lines)
> 
>      def run_test(testnum):
>          """Run a particular test number (the 'log test' command)
> @@ -43,7 +43,7 @@ def test_log(u_boot_console):
>             output = u_boot_console.run_command('log test %d' % testnum)
>          split = output.replace('\r', '').splitlines()
>          lines = iter(split)
> -        assert 'test %d' % testnum == lines.next()
> +        assert 'test %d' % testnum == next(lines)
>          return lines
> 
>      def test0():
> @@ -88,7 +88,7 @@ def test_log(u_boot_console):
>      def test10():
>          lines = run_test(10)
>          for i in range(7):
> -            assert 'log_test() level %d' % i == lines.next()
> +            assert 'log_test() level %d' % i == next(lines)
> 
>      # TODO(sjg at chromium.org): Consider structuring this as separate tests
>      cons = u_boot_console
> diff --git a/test/py/tests/test_mmc_wr.py b/test/py/tests/test_mmc_wr.py
> index 8b18781eac..2ce79f58e3 100644
> --- a/test/py/tests/test_mmc_wr.py
> +++ b/test/py/tests/test_mmc_wr.py
> @@ -65,41 +65,39 @@ def test_mmc_wr(u_boot_console, env__mmc_wr_config):
> 
> 
>      for i in range(test_iterations):
> -	# Generate random data
> -	cmd = 'random %s %x' % (src_addr, count_bytes)
> -	response = u_boot_console.run_command(cmd)
> -	good_response = '%d bytes filled with random data' % (count_bytes)
> -	assert good_response in response
> -
> -	# Select MMC device
> -	cmd = 'mmc dev %d' % devid
> -	if is_emmc:
> -		cmd += ' %d' % partid
> -	response = u_boot_console.run_command(cmd)
> -	assert 'no card present' not in response
> -	if is_emmc:
> -		partid_response = "(part %d)" % partid
> -	else:
> -		partid_response = ""
> -	good_response = 'mmc%d%s is current device' % (devid, partid_response)
> -	assert good_response in response
> -
> -	# Write data
> -	cmd = 'mmc write %s %x %x' % (src_addr, sector, count_sectors)
> -	response = u_boot_console.run_command(cmd)
> -	good_response = 'MMC write: dev # %d, block # %d, count %d ... %d blocks written: OK' % (
> -		devid, sector, count_sectors, count_sectors)
> -	assert good_response in response
> -
> -	# Read data
> -	cmd = 'mmc read %s %x %x' % (dst_addr, sector, count_sectors)
> -	response = u_boot_console.run_command(cmd)
> -	good_response = 'MMC read: dev # %d, block # %d, count %d ... %d blocks read: OK' % (
> -		devid, sector, count_sectors, count_sectors)
> -	assert good_response in response
> -
> -	# Compare src and dst data
> -	cmd = 'cmp.b %s %s %x' % (src_addr, dst_addr, count_bytes)
> -	response = u_boot_console.run_command(cmd)
> -	good_response = 'Total of %d byte(s) were the same' % (count_bytes)
> -	assert good_response in response
> +        # Generate random data
> +        cmd = 'random %s %x' % (src_addr, count_bytes)
> +        response = u_boot_console.run_command(cmd)
> +        good_response = '%d bytes filled with random data' % (count_bytes)
> +        assert good_response in response
> +
> +        # Select MMC device
> +        cmd = 'mmc dev %d' % devid
> +        if is_emmc:
> +            cmd += ' %d' % partid
> +        response = u_boot_console.run_command(cmd)
> +        assert 'no card present' not in response
> +        if is_emmc:
> +            partid_response = "(part %d)" % partid
> +        else:
> +            partid_response = ""
> +        good_response = 'mmc%d%s is current device' % (devid, partid_response)
> +        assert good_response in response
> +
> +        # Write data
> +        cmd = 'mmc write %s %x %x' % (src_addr, sector, count_sectors)
> +        response = u_boot_console.run_command(cmd)
> +        good_response = 'MMC write: dev # %d, block # %d, count %d ... %d blocks written: OK' % (devid, sector, count_sectors, count_sectors)
> +        assert good_response in response
> +
> +        # Read data
> +        cmd = 'mmc read %s %x %x' % (dst_addr, sector, count_sectors)
> +        response = u_boot_console.run_command(cmd)
> +        good_response = 'MMC read: dev # %d, block # %d, count %d ... %d blocks read: OK' % (devid, sector, count_sectors, count_sectors)
> +        assert good_response in response
> +
> +        # Compare src and dst data
> +        cmd = 'cmp.b %s %s %x' % (src_addr, dst_addr, count_bytes)
> +        response = u_boot_console.run_command(cmd)
> +        good_response = 'Total of %d byte(s) were the same' % (count_bytes)
> +        assert good_response in response
> --
> 2.23.0
> 

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20191019/c0123155/attachment.sig>

  reply	other threads:[~2019-10-19 11:22 UTC|newest]

Thread overview: 97+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-18 20:53 [U-Boot] [PATCH 00/10] Moving test/py to Python 3 Tom Rini
2019-10-18 20:53 ` [U-Boot] [PATCH 01/10] gitlab-ci: Fix indentation in some stanzas Tom Rini
2019-10-21 15:25   ` Simon Glass
2019-10-18 20:53 ` [U-Boot] [PATCH 02/10] gitlab-ci: Prepend to PATH rather than overwrite it Tom Rini
2019-10-21 15:25   ` Simon Glass
2019-10-18 20:53 ` [U-Boot] [PATCH 03/10] test/py: Fix pytest4 deprecation warnings Tom Rini
2019-10-21 15:25   ` Simon Glass
2019-10-21 15:51     ` Tom Rini
2019-10-18 20:53 ` [U-Boot] [PATCH 04/10] test/py: Automated conversion to Python 3 Tom Rini
2019-10-18 21:12   ` Stephen Warren
2019-10-18 22:08     ` Tom Rini
2019-10-19  5:25   ` Heinrich Schuchardt
2019-10-19  6:13     ` [U-Boot] [RFC v2 4/10] " Heinrich Schuchardt
2019-10-19 11:22       ` Tom Rini [this message]
2019-10-19 12:16     ` [U-Boot] [PATCH 04/10] " Tom Rini
2019-10-18 20:53 ` [U-Boot] [PATCH 05/10] test/py: Split mark to multiple lines Tom Rini
2019-10-18 20:53 ` [U-Boot] [PATCH 06/10] test/py: test_ut.py: Ensure we use bytes Tom Rini
2019-10-18 20:53 ` [U-Boot] [PATCH 07/10] test/py: Manual python3 fixes Tom Rini
2019-10-19  6:33   ` Heinrich Schuchardt
2019-10-18 20:53 ` [U-Boot] [PATCH 08/10] WORKAROUND: gitlab-ci: Rework how and when we use virtualenv in order to have python3 Tom Rini
2019-10-18 20:53 ` [U-Boot] [PATCH 09/10] WORKAROUND: test/py: Skip fs tests for now Tom Rini
2019-10-18 21:16   ` Stephen Warren
2019-10-18 22:07     ` Tom Rini
2019-10-18 20:53 ` [U-Boot] [PATCH 10/10] HACK: test.py: Disable EFI " Tom Rini
2019-10-18 21:17   ` Stephen Warren
2019-10-18 21:18 ` [U-Boot] [PATCH 00/10] Moving test/py to Python 3 Stephen Warren
2019-10-23  3:19 ` [U-Boot] [PATCHv2 00/13] " Tom Rini
2019-10-23  3:19   ` [U-Boot] [PATCHv2 01/13] gitlab-ci: Fix indentation in some stanzas Tom Rini
2019-10-23  3:19   ` [U-Boot] [PATCHv2 02/13] gitlab-ci: Prepend to PATH rather than replace it Tom Rini
2019-10-23  3:20   ` [U-Boot] [PATCHv2 03/13] test/py: Split mark to multiple lines Tom Rini
2019-10-24  0:59     ` Simon Glass
2019-10-23  3:20   ` [U-Boot] [PATCHv2 04/13] test/py: Fix pytest4 deprecation warnings Tom Rini
2019-10-24  0:59     ` Simon Glass
2019-10-23  3:20   ` [U-Boot] [PATCHv2 05/13] test/py: Automated conversion to Python 3 Tom Rini
2019-10-24  0:59     ` Simon Glass
2019-10-23  3:20   ` [U-Boot] [PATCHv2 06/13] test/py: Manual python3 fixes Tom Rini
2019-10-23 18:50     ` Stephen Warren
2019-10-23 19:01       ` Tom Rini
2019-10-23 19:27         ` Stephen Warren
2019-10-24  0:59     ` Simon Glass
2019-10-23  3:20   ` [U-Boot] [PATCHv2 07/13] test/py: test_ut.py: Ensure we use bytes Tom Rini
2019-10-24  0:59     ` Simon Glass
2019-10-23  3:20   ` [U-Boot] [PATCHv2 08/13] test/py: test_efi_selftest.py: Updates for python 3 support Tom Rini
2019-10-23 16:47     ` Stephen Warren
2019-10-24  0:59     ` Simon Glass
2019-10-23  3:20   ` [U-Boot] [PATCHv2 09/13] test/py: Update test_fs to decode check_output calls Tom Rini
2019-10-24  0:59     ` Simon Glass
2019-10-23  3:20   ` [U-Boot] [PATCHv2 10/13] test/py: Rework test.py to be a different kind of wrapper Tom Rini
2019-10-23 16:55     ` Stephen Warren
2019-10-23 16:58       ` Tom Rini
2019-10-23 17:03         ` Stephen Warren
2019-10-23 17:12           ` Tom Rini
2019-10-23 17:29             ` Stephen Warren
2019-10-23 18:04               ` Stephen Warren
2019-10-23 18:17                 ` Tom Rini
2019-10-23 21:11                   ` Stephen Warren
2019-10-23 21:37                     ` Tom Rini
2019-10-24  0:59     ` Simon Glass
2019-10-23  3:20   ` [U-Boot] [PATCHv2 11/13] test/py: Update docs, add requirements.txt for pip Tom Rini
2019-10-23 18:30     ` Stephen Warren
2019-10-23 18:49       ` Tom Rini
2019-10-24  0:59     ` Simon Glass
2019-10-23  3:20   ` [U-Boot] [PATCHv2 12/13] gitlab/travis: Rework how and when we use virtualenv in order to use python3 Tom Rini
2019-10-24  0:59     ` Simon Glass
2019-10-23  3:20   ` [U-Boot] [PATCHv2 13/13] test/py: Use raw strings more to avoid deprecation warnings Tom Rini
2019-10-24  0:59     ` Simon Glass
2019-10-24 15:59   ` [U-Boot] [PATCHv3 00/13] Moving test/py to Python 3 Tom Rini
2019-10-24 15:59     ` [U-Boot] [PATCHv3 01/13] gitlab-ci: Fix indentation in some stanzas Tom Rini
2019-11-01 13:31       ` Tom Rini
2019-10-24 15:59     ` [U-Boot] [PATCHv3 02/13] gitlab-ci: Prepend to PATH rather than replace it Tom Rini
2019-11-01 13:31       ` Tom Rini
2019-10-24 15:59     ` [U-Boot] [PATCHv3 03/13] test/py: Split mark to multiple lines Tom Rini
2019-11-01 13:31       ` Tom Rini
2019-10-24 15:59     ` [U-Boot] [PATCHv3 04/13] test/py: Fix pytest4 deprecation warnings Tom Rini
2019-11-01 13:32       ` Tom Rini
2019-10-24 15:59     ` [U-Boot] [PATCHv3 05/13] test/py: Automated conversion to Python 3 Tom Rini
2019-11-01 13:32       ` Tom Rini
2019-10-24 15:59     ` [U-Boot] [PATCHv3 06/13] test/py: Manual python3 fixes Tom Rini
2019-11-01 13:32       ` Tom Rini
2019-10-24 15:59     ` [U-Boot] [PATCHv3 07/13] test/py: test_ut.py: Ensure we use bytes Tom Rini
2019-11-01 13:32       ` Tom Rini
2019-10-24 15:59     ` [U-Boot] [PATCHv3 08/13] test/py: test_efi_selftest.py: Updates for python 3 support Tom Rini
2019-11-01 13:32       ` Tom Rini
2019-10-24 15:59     ` [U-Boot] [PATCHv3 09/13] test/py: Update test_fs to decode check_output calls Tom Rini
2019-11-01 13:32       ` Tom Rini
2019-10-24 15:59     ` [U-Boot] [PATCHv3 10/13] test/py: Rework test.py to be a different kind of wrapper Tom Rini
2019-11-01 13:32       ` Tom Rini
2019-10-24 15:59     ` [U-Boot] [PATCHv3 11/13] test/py: Update docs, add requirements.txt for pip Tom Rini
2019-11-01 13:32       ` Tom Rini
2019-10-24 15:59     ` [U-Boot] [PATCHv3 12/13] gitlab/travis: Rework how and when we use virtualenv in order to use python3 Tom Rini
2019-11-01 13:32       ` Tom Rini
2019-10-24 15:59     ` [U-Boot] [PATCHv3 13/13] test/py: Use raw strings more to avoid deprecation warnings Tom Rini
2019-11-01 13:32       ` Tom Rini
2019-10-24 16:01     ` [U-Boot] [PATCH 1/2] Dockerfile: Update to latest bionic tag Tom Rini
2019-10-24 16:01       ` [U-Boot] [PATCH 2/2] Dockerfile: Add python3-pip Tom Rini
2019-10-30 17:02         ` Tom Rini
2019-10-30 17:02       ` [U-Boot] [PATCH 1/2] Dockerfile: Update to latest bionic tag Tom Rini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191019112257.GA11173@bill-the-cat \
    --to=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox