From a3f9a4e0b6ec6c259312ad9c0bed2a97ee3508fa Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 9 Feb 2024 01:05:53 +0000 Subject: [PATCH] Christ, I'd forgotten how horrific the with syntax was <3.9 Can't use bracketed expressions to split multiple context managers across lines prior to Python 3.9. Have to use the horrid line-ending markers instead... --- nobodd/prep.py | 16 ++--- nobodd/server.py | 8 +-- tests/test_prep.py | 58 ++++++++--------- tests/test_server.py | 34 +++++----- tests/test_tftpd.py | 150 +++++++++++++++++++++---------------------- tox.ini | 16 +++++ 6 files changed, 149 insertions(+), 133 deletions(-) create mode 100644 tox.ini diff --git a/nobodd/prep.py b/nobodd/prep.py index 1db8179..8bdd674 100644 --- a/nobodd/prep.py +++ b/nobodd/prep.py @@ -96,10 +96,10 @@ def prepare_image(conf): conf.logger.info( 'Skipping resize; %s is already %d bytes or larger', conf.image, conf.size) - with ( - DiskImage(conf.image, access=mmap.ACCESS_WRITE) as img, - FatFileSystem(img.partitions[conf.boot_partition].data) as fs - ): + with \ + DiskImage(conf.image, access=mmap.ACCESS_WRITE) as img, \ + FatFileSystem(img.partitions[conf.boot_partition].data) as fs: + cmdline = fs.root / conf.cmdline conf.logger.info( 'Re-writing %s in partition %d', conf.cmdline, conf.boot_partition) @@ -128,10 +128,10 @@ def detect_partitions(conf): partition. """ conf.logger.info('Detecting partitions') - with ( - conf.image.open('rb') as img_file, - DiskImage(img_file) as img - ): + with \ + conf.image.open('rb') as img_file, \ + DiskImage(img_file) as img: + fat_types = ( {UUID('ebd0a0a2-b9e5-4433-87c0-68b6b72699c7'), UUID('c12a7328-f81f-11d2-ba4b-00a0c93ec93b')} diff --git a/nobodd/server.py b/nobodd/server.py index b3161c1..e9c66c3 100644 --- a/nobodd/server.py +++ b/nobodd/server.py @@ -195,10 +195,10 @@ def main(args=None): board.serial: board for board in conf.boards } - with ( - BootServer((conf.listen, conf.port), boards) as server, - DefaultSelector() as selector - ): + with \ + BootServer((conf.listen, conf.port), boards) as server, \ + DefaultSelector() as selector: + server.logger.addHandler(logging.StreamHandler(sys.stderr)) server.logger.setLevel(logging.DEBUG if debug else logging.INFO) server.logger.info('Ready') diff --git a/tests/test_prep.py b/tests/test_prep.py index 8a89de6..f79f912 100644 --- a/tests/test_prep.py +++ b/tests/test_prep.py @@ -25,10 +25,10 @@ def test_help(capsys): def test_error_exit_no_debug(capsys, monkeypatch): - with ( - mock.patch('nobodd.prep.get_parser') as get_parser, - monkeypatch.context() as m, - ): + with \ + mock.patch('nobodd.prep.get_parser') as get_parser, \ + monkeypatch.context() as m: + m.delenv('DEBUG', raising=False) get_parser.side_effect = RuntimeError('trouble is bad') @@ -38,10 +38,10 @@ def test_error_exit_no_debug(capsys, monkeypatch): def test_error_exit_with_debug(monkeypatch): - with ( - mock.patch('nobodd.prep.get_parser') as get_parser, - monkeypatch.context() as m, - ): + with \ + mock.patch('nobodd.prep.get_parser') as get_parser, \ + monkeypatch.context() as m: + m.setenv('DEBUG', '1') get_parser.side_effect = RuntimeError('trouble is bad') @@ -50,11 +50,11 @@ def test_error_exit_with_debug(monkeypatch): def test_error_exit_with_pdb(monkeypatch): - with ( - mock.patch('nobodd.prep.get_parser') as get_parser, - mock.patch('pdb.post_mortem') as post_mortem, - monkeypatch.context() as m - ): + with \ + mock.patch('nobodd.prep.get_parser') as get_parser, \ + mock.patch('pdb.post_mortem') as post_mortem, \ + monkeypatch.context() as m: + m.setenv('DEBUG', '2') get_parser.side_effect = RuntimeError('trouble is bad') @@ -72,10 +72,10 @@ def test_regular_operation(fat_disks_w): str(fat_disk) ]) == 0 assert fat_disk.stat().st_size == 50 * 1048576 - with ( - DiskImage(fat_disk) as img, - FatFileSystem(img.partitions[1].data) as fs, - ): + with \ + DiskImage(fat_disk) as img, \ + FatFileSystem(img.partitions[1].data) as fs: + assert (fs.root / 'cmdline.txt').read_text() == ( 'ip=dhcp nbdroot=myserver/myshare root=/dev/nbd0p5 ' 'console=serial0,115200 dwc_otg.lpm_enable=0 console=tty1 ' @@ -83,10 +83,10 @@ def test_regular_operation(fat_disks_w): def test_cmdline_no_newline(fat16_disk_w): - with ( - DiskImage(fat16_disk_w, access=mmap.ACCESS_WRITE) as img, - FatFileSystem(img.partitions[1].data) as fs - ): + with \ + DiskImage(fat16_disk_w, access=mmap.ACCESS_WRITE) as img, \ + FatFileSystem(img.partitions[1].data) as fs: + # Ensure the transformation works even when cmdline.txt has no newlines path = fs.root / 'cmdline.txt' path.write_text(path.read_text().rstrip('\n')) @@ -100,10 +100,10 @@ def test_cmdline_no_newline(fat16_disk_w): str(fat16_disk_w) ]) == 0 - with ( - DiskImage(fat16_disk_w) as img, - FatFileSystem(img.partitions[1].data) as fs, - ): + with \ + DiskImage(fat16_disk_w) as img, \ + FatFileSystem(img.partitions[1].data) as fs: + assert (fs.root / 'cmdline.txt').read_text() == ( 'ip=dhcp nbdroot=myserver/myshare root=/dev/nbd0p5 ' 'console=serial0,115200 dwc_otg.lpm_enable=0 console=tty1 ' @@ -184,10 +184,10 @@ def test_default_host_share(fat16_disk_w): str(fat16_disk_w) ]) == 0 - with ( - DiskImage(fat16_disk_w) as img, - FatFileSystem(img.partitions[1].data) as fs, - ): + with \ + DiskImage(fat16_disk_w) as img, \ + FatFileSystem(img.partitions[1].data) as fs: + assert (fs.root / 'cmdline.txt').read_text() == ( 'ip=dhcp nbdroot=louis.prima.org/fat16-mutable root=/dev/nbd0p5 ' 'console=serial0,115200 dwc_otg.lpm_enable=0 console=tty1 ' diff --git a/tests/test_server.py b/tests/test_server.py index 34cb86b..fc405cc 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -85,10 +85,10 @@ def test_sigterm(main_thread, capsys): def test_error_exit_no_debug(main_thread, capsys, monkeypatch): - with ( - mock.patch('nobodd.server.get_parser') as get_parser, - monkeypatch.context() as m, - ): + with \ + mock.patch('nobodd.server.get_parser') as get_parser, \ + monkeypatch.context() as m: + m.delenv('DEBUG', raising=False) get_parser.side_effect = RuntimeError('trouble is bad') @@ -102,10 +102,10 @@ def test_error_exit_no_debug(main_thread, capsys, monkeypatch): def test_error_exit_with_debug(main_thread, monkeypatch): - with ( - mock.patch('nobodd.server.get_parser') as get_parser, - monkeypatch.context() as m, - ): + with \ + mock.patch('nobodd.server.get_parser') as get_parser, \ + monkeypatch.context() as m: + m.setenv('DEBUG', '1') get_parser.side_effect = RuntimeError('trouble is bad') @@ -116,11 +116,11 @@ def test_error_exit_with_debug(main_thread, monkeypatch): def test_error_exit_with_pdb(main_thread, capsys, monkeypatch): - with ( - mock.patch('nobodd.server.get_parser') as get_parser, - mock.patch('pdb.post_mortem') as post_mortem, - monkeypatch.context() as m, - ): + with \ + mock.patch('nobodd.server.get_parser') as get_parser, \ + mock.patch('pdb.post_mortem') as post_mortem, \ + monkeypatch.context() as m: + m.setenv('DEBUG', '2') get_parser.side_effect = RuntimeError('trouble is bad') @@ -131,10 +131,10 @@ def test_error_exit_with_pdb(main_thread, capsys, monkeypatch): def test_regular_operation(fat16_disk, main_thread, capsys): - with ( - disk.DiskImage(fat16_disk) as img, - fs.FatFileSystem(img.partitions[1].data) as boot, - ): + with \ + disk.DiskImage(fat16_disk) as img, \ + fs.FatFileSystem(img.partitions[1].data) as boot: + expected = (boot.root / 'random').read_bytes() main_thread.argv = [ diff --git a/tests/test_tftpd.py b/tests/test_tftpd.py index 506c8c4..fba5143 100644 --- a/tests/test_tftpd.py +++ b/tests/test_tftpd.py @@ -208,10 +208,10 @@ def test_clientstate_transfer(localhost, initrd_img): def test_tftp_rrq_transfer(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + # All tests start with this to ensure previous tests have left the # session-scoped server in a "clean" state (see note in the tftp_server # fixture above) @@ -244,10 +244,10 @@ def test_tftp_rrq_transfer(tftp_server, caplog): def test_tftp_rrq_transfer_repeat_ack(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive client.settimeout(10) @@ -285,10 +285,10 @@ def test_tftp_rrq_transfer_repeat_ack(tftp_server, caplog): def test_tftp_rrq_transfer_future_ack(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive client.settimeout(10) @@ -316,10 +316,10 @@ def test_tftp_rrq_transfer_future_ack(tftp_server, caplog): def test_tftp_rrq_transfer_resend(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive client.settimeout(10) @@ -351,10 +351,10 @@ def test_tftp_rrq_transfer_resend(tftp_server, caplog): def test_tftp_rrq_transfer_with_options(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive client.settimeout(10) @@ -390,10 +390,10 @@ def test_tftp_rrq_transfer_with_options(tftp_server, caplog): def test_tftp_rrq_transfer_resend_and_die(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive # We're using a ludicrously short timeout below (the minimum permitted) @@ -434,10 +434,10 @@ def test_tftp_rrq_transfer_resend_and_die(tftp_server, caplog): def test_tftp_rrq_transfer_bad_options(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive client.settimeout(10) @@ -459,10 +459,10 @@ def test_tftp_rrq_transfer_bad_options(tftp_server, caplog): def test_tftp_rrq_transfer_bad_filename(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive client.settimeout(10) @@ -483,11 +483,11 @@ def test_tftp_rrq_transfer_bad_filename(tftp_server, caplog): def test_tftp_rrq_unknown_error(tftp_server, caplog): - with ( - mock.patch('nobodd.tftpd.TFTPBaseHandler.do_RRQ') as do_rrq, - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + mock.patch('nobodd.tftpd.TFTPBaseHandler.do_RRQ') as do_rrq, \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive do_rrq.side_effect = TypeError('something weird happened') @@ -508,10 +508,10 @@ def test_tftp_rrq_unknown_error(tftp_server, caplog): def test_tftp_rrq_os_error(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive client.settimeout(10) @@ -532,10 +532,10 @@ def test_tftp_rrq_os_error(tftp_server, caplog): def test_tftp_rrq_transfer_permission_error1(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive client.settimeout(10) @@ -556,10 +556,10 @@ def test_tftp_rrq_transfer_permission_error1(tftp_server, caplog): def test_tftp_rrq_transfer_permission_error2(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive client.settimeout(10) @@ -581,10 +581,10 @@ def test_tftp_rrq_transfer_permission_error2(tftp_server, caplog): def test_tftp_wrq_transfer(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive client.settimeout(10) @@ -607,10 +607,10 @@ def test_tftp_wrq_transfer(tftp_server, caplog): def test_tftp_client_error1(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive client.settimeout(10) @@ -626,10 +626,10 @@ def test_tftp_client_error1(tftp_server, caplog): def test_tftp_client_error2(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive client.settimeout(10) @@ -653,10 +653,10 @@ def test_tftp_client_error2(tftp_server, caplog): def test_tftp_bad_request(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive client.settimeout(10) @@ -676,11 +676,11 @@ def test_tftp_bad_request(tftp_server, caplog): def test_tftp_bad_client(tftp_server, caplog): - with ( - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client1, - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client2, - caplog.at_level(logging.INFO) - ): + with \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client1, \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client2, \ + caplog.at_level(logging.INFO): + assert not tftp_server.subs._alive # Start a valid transfer from client1... @@ -729,11 +729,11 @@ def test_tftp_bad_client(tftp_server, caplog): def test_tftp_shuts_down_transfers(tftp_root, cmdline_txt): # Set up our own one-shot SimpleTFTPServer as we need to shut it down # during this test... - with ( - SimpleTFTPServer(('127.0.0.1', 0), tftp_root) as server, - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client1, - socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client2, - ): + with \ + SimpleTFTPServer(('127.0.0.1', 0), tftp_root) as server, \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client1, \ + socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client2: \ + thread = Thread(target=server.serve_forever, daemon=True) thread.start() assert not server.subs._alive diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..d57e371 --- /dev/null +++ b/tox.ini @@ -0,0 +1,16 @@ +[tox] +envlist = {py37,py38,py39,py310,py311} + +[testenv] +basepython = + py37: python3.7 + py38: python3.8 + py39: python3.9 + py310: python3.10 + py311: python3.11 +deps = .[test] +usedevelop = True +commands = make test +setenv = + COVERAGE_FILE=.coverage.{envname} +allowlist_externals = make