Update ruff to v0.8.x, reformat and re-lint (part 1 of 2)
Marco Ricci

Marco Ricci commited on 2025-01-07 22:44:39
Zeige 16 geänderte Dateien mit 407 Einfügungen und 400 Löschungen.


We update `ruff` to v0.8.x and reformat the sources.  Most
conspicuously, `assert` statements typically no longer break the
condition to test, and rather push the error message to the next line
instead.  Also, some implicit string concatenations are undone if they
*do* fit onto a single line.

We also re-lint the sources, and commit part of the linting fixes.
Specifically, omissions in the docstring (raised exceptions, return
values) are now marked as linting errors on the docstring itself,
instead of at the omitted object (`raise` or `return` statement).
Alternatively, we add the missing info to the docstring.  We also commit
linting fixes regarding improper usage of underscores in variable names
(leading underscore instead of trailing underscore on temporary
variables).  Finally, we correct some improper calls to the logging
system (root logger instead of application logger).
... ...
@@ -123,7 +123,7 @@ detached = false
123 123
 [tool.hatch.envs.hatch-static-analysis]
124 124
 config-path = "/dev/null"
125 125
 dependencies = [
126
-  "ruff ~= 0.6.0",
126
+  "ruff ~= 0.8.0",
127 127
 ]
128 128
 
129 129
 [tool.hatch.envs.hatch-test]
... ...
@@ -245,7 +245,7 @@ select = [
245 245
     'ANN', 'ASYNC', 'S', 'BLE', 'FBT', 'B', 'A', 'COM',
246 246
     'CPY', 'C4', 'DTZ', 'T10', 'DJ', 'EM', 'EXE', 'FA',
247 247
     'ISC', 'ICN', 'LOG', 'G', 'INP', 'PIE', 'T20', 'PYI',
248
-    'PT', 'Q', 'RET', 'SLF', 'SLOT', 'SIM', 'TID', 'TCH',
248
+    'PT', 'Q', 'RET', 'SLF', 'SLOT', 'SIM', 'TID', 'TC',
249 249
     'INT', 'ARG',
250 250
     # We currently do not use pathlib. Disable 'PTH'.
251 251
     'TD',
... ...
@@ -1245,7 +1245,7 @@ def _write_pot_file(fileobj: TextIO) -> None:  # pragma: no cover
1245 1245
     appearing in the enums of this module.  Certain parts of the
1246 1246
     .po header are hard-coded, as is the source filename.
1247 1247
 
1248
-    """
1248
+    """  # noqa: DOC501
1249 1249
     entries: dict[
1250 1250
         str,
1251 1251
         dict[
... ...
@@ -1266,7 +1266,7 @@ def _write_pot_file(fileobj: TextIO) -> None:  # pragma: no cover
1266 1266
                 msg in entries.setdefault(ctx, {})
1267 1267
                 and entries[ctx][msg] != member
1268 1268
             ):
1269
-                raise AssertionError(  # noqa: DOC501,TRY003
1269
+                raise AssertionError(  # noqa: TRY003
1270 1270
                     f'Duplicate entry for ({ctx!r}, {msg!r}): '  # noqa: EM102
1271 1271
                     f'{entries[ctx][msg]!r} and {member!r}'
1272 1272
                 )
... ...
@@ -288,8 +288,7 @@ def validate_vault_config(  # noqa: C901,PLR0912
288 288
     def err_unknown_setting(key: str, path: Sequence[str], /) -> str:
289 289
         json_path_str = json_path(path)
290 290
         return (
291
-            f'vault config entry {json_path_str} uses '
292
-            f'unknown setting {key!r}'
291
+            f'vault config entry {json_path_str} uses unknown setting {key!r}'
293 292
         )
294 293
 
295 294
     def err_bad_number(
... ...
@@ -370,7 +369,7 @@ def is_vault_config(obj: Any) -> TypeIs[VaultConfig]:  # noqa: ANN401
370 369
     Returns:
371 370
         True if this is a vault config, false otherwise.
372 371
 
373
-    """
372
+    """  # noqa: DOC501
374 373
     try:
375 374
         validate_vault_config(
376 375
             obj,
... ...
@@ -379,7 +378,7 @@ def is_vault_config(obj: Any) -> TypeIs[VaultConfig]:  # noqa: ANN401
379 378
         )
380 379
     except (TypeError, ValueError) as exc:
381 380
         if 'vault config ' not in str(exc):  # pragma: no cover
382
-            raise  # noqa: DOC501
381
+            raise
383 382
         return False
384 383
     return True
385 384
 
... ...
@@ -1124,9 +1124,9 @@ def _shell_complete_path(
1124 1124
     parameter: click.Parameter,
1125 1125
     value: str,
1126 1126
 ) -> list[str | click.shell_completion.CompletionItem]:
1127
-    """Request standard path completion for the `path` argument."""
1127
+    """Request standard path completion for the `path` argument."""  # noqa: DOC201
1128 1128
     del ctx, parameter, value
1129
-    return [click.shell_completion.CompletionItem('', type='file')]  # noqa: DOC201
1129
+    return [click.shell_completion.CompletionItem('', type='file')]
1130 1130
 
1131 1131
 
1132 1132
 # The standard `click` shell completion scripts serialize the completion
... ...
@@ -1294,7 +1294,7 @@ class _DefaultToVaultGroup(CommandWithHelpGroups, click.Group):
1294 1294
         derivepassphrase".  Furthermore, all "pragma" and "noqa" comments
1295 1295
         are also modifications for derivepassphrase.
1296 1296
 
1297
-        """
1297
+        """  # noqa: DOC201
1298 1298
         cmd_name = click.utils.make_str(args[0])
1299 1299
 
1300 1300
         # Get the command
... ...
@@ -1335,7 +1335,7 @@ class _DefaultToVaultGroup(CommandWithHelpGroups, click.Group):
1335 1335
             #
1336 1336
             # END modifications for derivepassphrase
1337 1337
             ####
1338
-        return cmd_name if cmd else None, cmd, args[1:]  # noqa: DOC201
1338
+        return cmd_name if cmd else None, cmd, args[1:]
1339 1339
 
1340 1340
 
1341 1341
 class _TopLevelCLIEntryPoint(_DefaultToVaultGroup):
... ...
@@ -1800,7 +1800,7 @@ def _save_config(config: _types.VaultConfig, /) -> None:
1800 1800
         ValueError:
1801 1801
             The data cannot be stored as a vault(1)-compatible config.
1802 1802
 
1803
-    """
1803
+    """  # noqa: DOC501
1804 1804
     if not _types.is_vault_config(config):
1805 1805
         raise ValueError(_INVALID_VAULT_CONFIG)
1806 1806
     filename = _config_filename(subsystem='vault')
... ...
@@ -1809,7 +1809,7 @@ def _save_config(config: _types.VaultConfig, /) -> None:
1809 1809
         os.makedirs(filedir, exist_ok=False)
1810 1810
     except FileExistsError:
1811 1811
         if not os.path.isdir(filedir):
1812
-            raise  # noqa: DOC501
1812
+            raise
1813 1813
     with open(filename, 'w', encoding='UTF-8') as fileobj:
1814 1814
         json.dump(config, fileobj)
1815 1815
 
... ...
@@ -2795,7 +2795,7 @@ def derivepassphrase_vault(  # noqa: C901,PLR0912,PLR0913,PLR0914,PLR0915
2795 2795
             `--export`, selects the format to export the current
2796 2796
             configuration as: JSON ("json", default) or POSIX sh ("sh").
2797 2797
 
2798
-    """
2798
+    """  # noqa: DOC501
2799 2799
     logger = logging.getLogger(PROG_NAME)
2800 2800
     deprecation = logging.getLogger(PROG_NAME + '.deprecation')
2801 2801
     service_metavar = _msg.TranslatedString(_msg.Label.VAULT_METAVAR_SERVICE)
... ...
@@ -2818,7 +2818,7 @@ def derivepassphrase_vault(  # noqa: C901,PLR0912,PLR0913,PLR0914,PLR0915
2818 2818
             elif isinstance(param, StandardOption):
2819 2819
                 group = StandardOption
2820 2820
             elif isinstance(param, OptionGroupOption):  # pragma: no cover
2821
-                raise AssertionError(  # noqa: DOC501,TRY003,TRY004
2821
+                raise AssertionError(  # noqa: TRY003,TRY004
2822 2822
                     f'Unknown option group for {param!r}'  # noqa: EM102
2823 2823
                 )
2824 2824
             else:
... ...
@@ -3003,7 +3003,7 @@ def derivepassphrase_vault(  # noqa: C901,PLR0912,PLR0913,PLR0914,PLR0915
3003 3003
                 param=param.opts[0],
3004 3004
                 service_metavar=service_metavar,
3005 3005
             )
3006
-            raise click.UsageError(str(err_msg))  # noqa: DOC501
3006
+            raise click.UsageError(str(err_msg))
3007 3007
     sv_options = [params_by_str['--notes'], params_by_str['--delete']]
3008 3008
     for param in sv_options:
3009 3009
         if is_param_set(param) and not service is not None:
... ...
@@ -3452,9 +3452,9 @@ def derivepassphrase_vault(  # noqa: C901,PLR0912,PLR0913,PLR0914,PLR0915
3452 3452
                 for setting in unset_settings:
3453 3453
                     subtree.pop(setting, None)
3454 3454
             subtree.update(view)
3455
-            assert _types.is_vault_config(
3456
-                configuration
3457
-            ), f'Invalid vault configuration: {configuration!r}'
3455
+            assert _types.is_vault_config(configuration), (
3456
+                f'Invalid vault configuration: {configuration!r}'
3457
+            )
3458 3458
             put_config(configuration)
3459 3459
         else:
3460 3460
             assert service is not None
... ...
@@ -739,9 +739,9 @@ def export_storeroom_data(  # noqa: C901,PLR0912,PLR0914,PLR0915
739 739
                 # Of course, the type checker doesn't necessarily know
740 740
                 # this, so we need to use assertions anyway.
741 741
                 maybe_obj = obj.get(part)
742
-                assert isinstance(
743
-                    maybe_obj, dict
744
-                ), f'Cannot traverse storage path {_dir!r}'
742
+                assert isinstance(maybe_obj, dict), (
743
+                    f'Cannot traverse storage path {_dir!r}'
744
+                )
745 745
                 obj = maybe_obj
746 746
         if set(obj.keys()) != set(namelist):
747 747
             msg = f'Object key mismatch for path {_dir!r}'
... ...
@@ -112,6 +112,10 @@ class VaultNativeConfigParser(abc.ABC):
112 112
                 If this is a text string, then the UTF-8 encoding of the
113 113
                 string is used as the binary password.
114 114
 
115
+        Raises:
116
+            ValueError:
117
+                The password must not be empty.
118
+
115 119
         Warning:
116 120
             Non-public class, provided for didactical and educational
117 121
             purposes only. Subject to change without notice, including
... ...
@@ -120,7 +124,7 @@ class VaultNativeConfigParser(abc.ABC):
120 124
         """
121 125
         if not password:
122 126
             msg = 'Password must not be empty'
123
-            raise ValueError(msg)  # noqa: DOC501
127
+            raise ValueError(msg)
124 128
         self._contents = bytes(contents)
125 129
         self._iv_size = 0
126 130
         self._mac_size = 0
... ...
@@ -208,12 +212,12 @@ class VaultNativeConfigParser(abc.ABC):
208 212
     def _derive_keys(self) -> None:
209 213
         logger.info('Deriving an encryption and signing key')
210 214
         self._generate_keys()
211
-        assert (
212
-            len(self._encryption_key) == self._encryption_key_size
213
-        ), 'Derived encryption key is invalid'
214
-        assert (
215
-            len(self._signing_key) == self._signing_key_size
216
-        ), 'Derived signing key is invalid'
215
+        assert len(self._encryption_key) == self._encryption_key_size, (
216
+            'Derived encryption key is invalid'
217
+        )
218
+        assert len(self._signing_key) == self._signing_key_size, (
219
+            'Derived signing key is invalid'
220
+        )
217 221
 
218 222
     @abc.abstractmethod
219 223
     def _generate_keys(self) -> None:
... ...
@@ -348,7 +352,7 @@ class VaultNativeV02ConfigParser(VaultNativeConfigParser):
348 352
             buffer = bytearray()
349 353
             last_block = b''
350 354
             salt = b''
351
-            logging.debug(
355
+            logger.debug(
352 356
                 (
353 357
                     'data = %s, salt = %s, key_size = %s, iv_size = %s, '
354 358
                     'buffer length = %s, buffer = %s'
... ...
@@ -371,10 +375,10 @@ class VaultNativeV02ConfigParser(VaultNativeConfigParser):
371 375
                 block.update(salt)
372 376
                 last_block = block.finalize()
373 377
                 buffer.extend(last_block)
374
-                logging.debug(
378
+                logger.debug(
375 379
                     'buffer length = %s, buffer = %s', len(buffer), _h(buffer)
376 380
                 )
377
-            logging.debug(
381
+            logger.debug(
378 382
                 'encryption_key = %s, iv = %s',
379 383
                 _h(buffer[:key_size]),
380 384
                 _h(buffer[key_size:total_size]),
... ...
@@ -457,13 +461,11 @@ def export_vault_native_data(
457 461
                 stored_exception = exc
458 462
         else:  # pragma: no cover
459 463
             msg = (
460
-                f'Invalid vault native configuration format: '
461
-                f'{config_format!r}'
464
+                f'Invalid vault native configuration format: {config_format!r}'
462 465
             )
463 466
             raise ValueError(msg)
464 467
     msg = (
465
-        f'Not a valid vault native configuration. '
466
-        f'(We tried: {try_formats!r}.)'
468
+        f'Not a valid vault native configuration. (We tried: {try_formats!r}.)'
467 469
     )
468 470
     raise stored_exception or ValueError(msg)
469 471
 
... ...
@@ -194,7 +194,7 @@ class Sequin:
194 194
             >>> Sequin._big_endian_number([1, 7, 5, 5], base=8) == 0o1755
195 195
             True
196 196
 
197
-        """
197
+        """  # noqa: DOC501
198 198
         if base < 2:  # noqa: PLR2004
199 199
             msg = f'invalid base: {base!r}'
200 200
             raise ValueError(msg)
... ...
@@ -206,7 +206,7 @@ class Sequin:
206 206
             x = digits[i]
207 207
             if not isinstance(x, int):
208 208
                 msg = f'not an integer: {x!r}'
209
-                raise TypeError(msg)  # noqa: DOC501
209
+                raise TypeError(msg)
210 210
             if x not in allowed_range:
211 211
                 msg = f'invalid base {base!r} digit: {x!r}'
212 212
                 raise ValueError(msg)
... ...
@@ -201,12 +201,12 @@ class SSHAgentClient:
201 201
             >>> SSHAgentClient.string(b'ssh-rsa')
202 202
             b'\x00\x00\x00\x07ssh-rsa'
203 203
 
204
-        """
204
+        """  # noqa: DOC501
205 205
         try:
206 206
             payload = memoryview(payload)
207 207
         except TypeError as e:
208 208
             msg = 'invalid payload type'
209
-            raise TypeError(msg) from e  # noqa: DOC501
209
+            raise TypeError(msg) from e
210 210
         ret = bytearray()
211 211
         ret.extend(cls.uint32(len(payload)))
212 212
         ret.extend(payload)
... ...
@@ -326,7 +326,7 @@ class SSHAgentClient:
326 326
                 `conn` was a socket or `None`, and there was an error
327 327
                 setting up a socket connection to the agent.
328 328
 
329
-        """
329
+        """  # noqa: DOC501
330 330
         # Use match/case here once Python 3.9 becomes unsupported.
331 331
         if isinstance(conn, SSHAgentClient):
332 332
             with contextlib.nullcontext():
... ...
@@ -337,7 +337,7 @@ class SSHAgentClient:
337 337
         else:  # pragma: no cover
338 338
             assert_never(conn)
339 339
             msg = f'invalid connection hint: {conn!r}'
340
-            raise TypeError(msg)  # noqa: DOC501
340
+            raise TypeError(msg)
341 341
 
342 342
     def _agent_is_pageant(self) -> bool:
343 343
         """Return True if we are connected to Pageant.
... ...
@@ -641,10 +641,10 @@ class SSHAgentClient:
641 641
         msg = 'Malformed response from SSH agent'
642 642
         msg2 = 'Extension response message does not match request'
643 643
         try:
644
-            _query, response_data = self.unstring_prefix(response_data)
644
+            query, response_data = self.unstring_prefix(response_data)
645 645
         except ValueError as e:
646 646
             raise RuntimeError(msg) from e
647
-        if bytes(_query) != b'query':
647
+        if bytes(query) != b'query':
648 648
             raise RuntimeError(msg2)
649 649
         while response_data:
650 650
             try:
... ...
@@ -232,6 +232,9 @@ class Vault:
232 232
         Returns:
233 233
             The estimated sufficient hash length.
234 234
 
235
+        Raises:
236
+            ValueError: The safety factor is less than 1, or not finite.
237
+
235 238
         Warning:
236 239
             This is a heuristic, not an exact computation; it may
237 240
             underestimate the true necessary hash length.  It is
... ...
@@ -239,15 +242,15 @@ class Vault:
239 242
             hash length, usually by doubling the hash length each time
240 243
             it does not yet prove so.
241 244
 
242
-        """
245
+        """  # noqa: DOC501
243 246
         try:
244 247
             safety_factor = float(safety_factor)
245 248
         except TypeError as e:
246 249
             msg = f'invalid safety factor: not a float: {safety_factor!r}'
247
-            raise TypeError(msg) from e  # noqa: DOC501
250
+            raise TypeError(msg) from e
248 251
         if not math.isfinite(safety_factor) or safety_factor < 1.0:
249 252
             msg = f'invalid safety factor {safety_factor!r}'
250
-            raise ValueError(msg)  # noqa: DOC501
253
+            raise ValueError(msg)
251 254
         # Ensure the bound is strictly positive.
252 255
         entropy_bound = max(1, self._entropy())
253 256
         return int(math.ceil(safety_factor * entropy_bound / 8))
... ...
@@ -254,7 +254,9 @@ def running_ssh_agent(  # pragma: no cover
254 254
                 assert (
255 255
                     os.environ.get('SSH_AUTH_SOCK', None)
256 256
                     == startup_ssh_auth_sock
257
-                ), f'SSH_AUTH_SOCK mismatch when checking for spawnable {exec_name}'
257
+                ), (
258
+                    f'SSH_AUTH_SOCK mismatch when checking for spawnable {exec_name}'
259
+                )
258 260
                 proc = spawn_func(executable=shutil.which(exec_name), env={})
259 261
                 if proc is None:
260 262
                     continue
... ...
@@ -370,7 +372,9 @@ def spawn_ssh_agent(
370 372
         else:
371 373
             assert (
372 374
                 os.environ.get('SSH_AUTH_SOCK', None) == startup_ssh_auth_sock
373
-            ), f'SSH_AUTH_SOCK mismatch when checking for spawnable {exec_name}'
375
+            ), (
376
+                f'SSH_AUTH_SOCK mismatch when checking for spawnable {exec_name}'
377
+            )
374 378
             proc = spawn_func(
375 379
                 executable=shutil.which(exec_name), env=agent_env
376 380
             )
... ...
@@ -310,12 +310,12 @@ class TestAllCLI:
310 310
             monkeypatch=monkeypatch,
311 311
             runner=runner,
312 312
         ):
313
-            _result = runner.invoke(
313
+            result_ = runner.invoke(
314 314
                 cli.derivepassphrase,
315 315
                 [*command, *arguments, *non_eager_arguments],
316 316
                 catch_exceptions=False,
317 317
             )
318
-            result = tests.ReadableResult.parse(_result)
318
+            result = tests.ReadableResult.parse(result_)
319 319
         assert result.clean_exit(empty_stderr=True), 'expected clean exit'
320 320
 
321 321
     @pytest.mark.parametrize('no_color', [False, True])
... ...
@@ -351,22 +351,22 @@ class TestAllCLI:
351 351
                 monkeypatch.setenv('NO_COLOR', 'yes')
352 352
             if force_color:
353 353
                 monkeypatch.setenv('FORCE_COLOR', 'yes')
354
-            _result = runner.invoke(
354
+            result_ = runner.invoke(
355 355
                 cli.derivepassphrase,
356 356
                 command_line,
357 357
                 input=input,
358 358
                 catch_exceptions=False,
359 359
                 color=isatty,
360 360
             )
361
-            result = tests.ReadableResult.parse(_result)
361
+            result = tests.ReadableResult.parse(result_)
362 362
         assert (
363 363
             not color
364 364
             or '\x1b[0m' in result.stderr
365 365
             or '\x1b[m' in result.stderr
366 366
         ), 'Expected color, but found no ANSI reset sequence'
367
-        assert (
368
-            color or '\x1b[' not in result.stderr
369
-        ), 'Expected no color, but found an ANSI control sequence'
367
+        assert color or '\x1b[' not in result.stderr, (
368
+            'Expected no color, but found an ANSI control sequence'
369
+        )
370 370
 
371 371
 
372 372
 class TestCLI:
... ...
@@ -379,12 +379,12 @@ class TestCLI:
379 379
             monkeypatch=monkeypatch,
380 380
             runner=runner,
381 381
         ):
382
-            _result = runner.invoke(
382
+            result_ = runner.invoke(
383 383
                 cli.derivepassphrase_vault,
384 384
                 ['--help'],
385 385
                 catch_exceptions=False,
386 386
             )
387
-            result = tests.ReadableResult.parse(_result)
387
+            result = tests.ReadableResult.parse(result_)
388 388
         assert result.clean_exit(
389 389
             empty_stderr=True, output='Passphrase generation:\n'
390 390
         ), 'expected clean exit, and option groups in help text'
... ...
@@ -401,18 +401,18 @@ class TestCLI:
401 401
             monkeypatch=monkeypatch,
402 402
             runner=runner,
403 403
         ):
404
-            _result = runner.invoke(
404
+            result_ = runner.invoke(
405 405
                 cli.derivepassphrase_vault,
406 406
                 ['--version'],
407 407
                 catch_exceptions=False,
408 408
             )
409
-            result = tests.ReadableResult.parse(_result)
410
-        assert result.clean_exit(
411
-            empty_stderr=True, output=cli.PROG_NAME
412
-        ), 'expected clean exit, and program name in version text'
413
-        assert result.clean_exit(
414
-            empty_stderr=True, output=cli.__version__
415
-        ), 'expected clean exit, and version in help text'
409
+            result = tests.ReadableResult.parse(result_)
410
+        assert result.clean_exit(empty_stderr=True, output=cli.PROG_NAME), (
411
+            'expected clean exit, and program name in version text'
412
+        )
413
+        assert result.clean_exit(empty_stderr=True, output=cli.__version__), (
414
+            'expected clean exit, and version in help text'
415
+        )
416 416
 
417 417
     @pytest.mark.parametrize(
418 418
         'charset_name', ['lower', 'upper', 'number', 'space', 'dash', 'symbol']
... ...
@@ -428,18 +428,18 @@ class TestCLI:
428 428
             monkeypatch=monkeypatch,
429 429
             runner=runner,
430 430
         ):
431
-            _result = runner.invoke(
431
+            result_ = runner.invoke(
432 432
                 cli.derivepassphrase_vault,
433 433
                 [option, '0', '-p', '--', DUMMY_SERVICE],
434 434
                 input=DUMMY_PASSPHRASE,
435 435
                 catch_exceptions=False,
436 436
             )
437
-            result = tests.ReadableResult.parse(_result)
437
+            result = tests.ReadableResult.parse(result_)
438 438
         assert result.clean_exit(empty_stderr=True), 'expected clean exit:'
439 439
         for c in charset:
440
-            assert (
441
-                c not in result.output
442
-            ), f'derived password contains forbidden character {c!r}'
440
+            assert c not in result.output, (
441
+                f'derived password contains forbidden character {c!r}'
442
+            )
443 443
 
444 444
     def test_202_disable_repetition(
445 445
         self, monkeypatch: pytest.MonkeyPatch
... ...
@@ -450,16 +450,16 @@ class TestCLI:
450 450
             monkeypatch=monkeypatch,
451 451
             runner=runner,
452 452
         ):
453
-            _result = runner.invoke(
453
+            result_ = runner.invoke(
454 454
                 cli.derivepassphrase_vault,
455 455
                 ['--repeat', '0', '-p', '--', DUMMY_SERVICE],
456 456
                 input=DUMMY_PASSPHRASE,
457 457
                 catch_exceptions=False,
458 458
             )
459
-            result = tests.ReadableResult.parse(_result)
460
-        assert result.clean_exit(
461
-            empty_stderr=True
462
-        ), 'expected clean exit and empty stderr'
459
+            result = tests.ReadableResult.parse(result_)
460
+        assert result.clean_exit(empty_stderr=True), (
461
+            'expected clean exit and empty stderr'
462
+        )
463 463
         passphrase = result.output.rstrip('\r\n')
464 464
         for i in range(len(passphrase) - 1):
465 465
             assert passphrase[i : i + 1] != passphrase[i + 1 : i + 2], (
... ...
@@ -503,22 +503,22 @@ class TestCLI:
503 503
             monkeypatch.setattr(
504 504
                 vault.Vault, 'phrase_from_key', tests.phrase_from_key
505 505
             )
506
-            _result = runner.invoke(
506
+            result_ = runner.invoke(
507 507
                 cli.derivepassphrase_vault,
508 508
                 ['--', DUMMY_SERVICE],
509 509
                 catch_exceptions=False,
510 510
             )
511
-        result = tests.ReadableResult.parse(_result)
512
-        assert result.clean_exit(
513
-            empty_stderr=True
514
-        ), 'expected clean exit and empty stderr'
515
-        assert _result.stdout_bytes
516
-        assert (
517
-            _result.stdout_bytes.rstrip(b'\n') != DUMMY_RESULT_PASSPHRASE
518
-        ), 'known false output: phrase-based instead of key-based'
519
-        assert (
520
-            _result.stdout_bytes.rstrip(b'\n') == DUMMY_RESULT_KEY1
521
-        ), 'expected known output'
511
+        result = tests.ReadableResult.parse(result_)
512
+        assert result.clean_exit(empty_stderr=True), (
513
+            'expected clean exit and empty stderr'
514
+        )
515
+        assert result_.stdout_bytes
516
+        assert result_.stdout_bytes.rstrip(b'\n') != DUMMY_RESULT_PASSPHRASE, (
517
+            'known false output: phrase-based instead of key-based'
518
+        )
519
+        assert result_.stdout_bytes.rstrip(b'\n') == DUMMY_RESULT_KEY1, (
520
+            'expected known output'
521
+        )
522 522
 
523 523
     def test_204b_key_from_command_line(
524 524
         self, monkeypatch: pytest.MonkeyPatch
... ...
@@ -535,22 +535,22 @@ class TestCLI:
535 535
             monkeypatch.setattr(
536 536
                 vault.Vault, 'phrase_from_key', tests.phrase_from_key
537 537
             )
538
-            _result = runner.invoke(
538
+            result_ = runner.invoke(
539 539
                 cli.derivepassphrase_vault,
540 540
                 ['-k', '--', DUMMY_SERVICE],
541 541
                 input='1\n',
542 542
                 catch_exceptions=False,
543 543
             )
544
-        result = tests.ReadableResult.parse(_result)
544
+        result = tests.ReadableResult.parse(result_)
545 545
         assert result.clean_exit(), 'expected clean exit'
546
-        assert _result.stdout_bytes, 'expected program output'
547
-        last_line = _result.stdout_bytes.splitlines(True)[-1]
548
-        assert (
549
-            last_line.rstrip(b'\n') != DUMMY_RESULT_PASSPHRASE
550
-        ), 'known false output: phrase-based instead of key-based'
551
-        assert (
552
-            last_line.rstrip(b'\n') == DUMMY_RESULT_KEY1
553
-        ), 'expected known output'
546
+        assert result_.stdout_bytes, 'expected program output'
547
+        last_line = result_.stdout_bytes.splitlines(True)[-1]
548
+        assert last_line.rstrip(b'\n') != DUMMY_RESULT_PASSPHRASE, (
549
+            'known false output: phrase-based instead of key-based'
550
+        )
551
+        assert last_line.rstrip(b'\n') == DUMMY_RESULT_KEY1, (
552
+            'expected known output'
553
+        )
554 554
 
555 555
     @pytest.mark.parametrize(
556 556
         'config',
... ...
@@ -593,18 +593,18 @@ class TestCLI:
593 593
             with tests.isolated_vault_config(
594 594
                 monkeypatch=monkeypatch, runner=runner, vault_config=config
595 595
             ):
596
-                _result = runner.invoke(
596
+                result_ = runner.invoke(
597 597
                     cli.derivepassphrase_vault,
598 598
                     ['-k', '--', DUMMY_SERVICE],
599 599
                     input=f'{key_index}\n',
600 600
                 )
601
-        result = tests.ReadableResult.parse(_result)
601
+        result = tests.ReadableResult.parse(result_)
602 602
         assert result.clean_exit(), 'expected clean exit'
603 603
         assert result.output, 'expected program output'
604 604
         assert result.stderr, 'expected stderr'
605
-        assert (
606
-            'Error:' not in result.stderr
607
-        ), 'expected no error messages on stderr'
605
+        assert 'Error:' not in result.stderr, (
606
+            'expected no error messages on stderr'
607
+        )
608 608
 
609 609
     def test_205_service_phrase_if_key_in_global_config(
610 610
         self,
... ...
@@ -631,21 +631,21 @@ class TestCLI:
631 631
                     },
632 632
                 },
633 633
             ):
634
-                _result = runner.invoke(
634
+                result_ = runner.invoke(
635 635
                     cli.derivepassphrase_vault,
636 636
                     ['--', DUMMY_SERVICE],
637 637
                     catch_exceptions=False,
638 638
                 )
639
-        result = tests.ReadableResult.parse(_result)
639
+        result = tests.ReadableResult.parse(result_)
640 640
         assert result.clean_exit(), 'expected clean exit'
641
-        assert _result.stdout_bytes, 'expected program output'
642
-        last_line = _result.stdout_bytes.splitlines(True)[-1]
643
-        assert (
644
-            last_line.rstrip(b'\n') != DUMMY_RESULT_PASSPHRASE
645
-        ), 'known false output: phrase-based instead of key-based'
646
-        assert (
647
-            last_line.rstrip(b'\n') == DUMMY_RESULT_KEY1
648
-        ), 'expected known output'
641
+        assert result_.stdout_bytes, 'expected program output'
642
+        last_line = result_.stdout_bytes.splitlines(True)[-1]
643
+        assert last_line.rstrip(b'\n') != DUMMY_RESULT_PASSPHRASE, (
644
+            'known false output: phrase-based instead of key-based'
645
+        )
646
+        assert last_line.rstrip(b'\n') == DUMMY_RESULT_KEY1, (
647
+            'expected known output'
648
+        )
649 649
 
650 650
     @pytest.mark.parametrize(
651 651
         ['config', 'command_line'],
... ...
@@ -700,13 +700,13 @@ class TestCLI:
700 700
                 runner=runner,
701 701
                 vault_config=config,
702 702
             ):
703
-                _result = runner.invoke(
703
+                result_ = runner.invoke(
704 704
                     cli.derivepassphrase_vault,
705 705
                     command_line,
706 706
                     input=DUMMY_PASSPHRASE,
707 707
                     catch_exceptions=False,
708 708
                 )
709
-        result = tests.ReadableResult.parse(_result)
709
+        result = tests.ReadableResult.parse(result_)
710 710
         assert result.clean_exit(), 'expected clean exit'
711 711
         assert not result.output.strip(), 'expected no program output'
712 712
         assert result.stderr, 'expected known error output'
... ...
@@ -746,16 +746,16 @@ class TestCLI:
746 746
             runner=runner,
747 747
         ):
748 748
             for value in '-42', 'invalid':
749
-                _result = runner.invoke(
749
+                result_ = runner.invoke(
750 750
                     cli.derivepassphrase_vault,
751 751
                     [option, value, '-p', '--', DUMMY_SERVICE],
752 752
                     input=DUMMY_PASSPHRASE,
753 753
                     catch_exceptions=False,
754 754
                 )
755
-                result = tests.ReadableResult.parse(_result)
756
-                assert result.error_exit(
757
-                    error='Invalid value'
758
-                ), 'expected error exit and known error message'
755
+                result = tests.ReadableResult.parse(result_)
756
+                assert result.error_exit(error='Invalid value'), (
757
+                    'expected error exit and known error message'
758
+                )
759 759
 
760 760
     @pytest.mark.parametrize(
761 761
         ['options', 'service', 'input', 'check_success'],
... ...
@@ -780,26 +780,26 @@ class TestCLI:
780 780
             runner=runner,
781 781
             vault_config={'global': {'phrase': 'abc'}, 'services': {}},
782 782
         ):
783
-            _result = runner.invoke(
783
+            result_ = runner.invoke(
784 784
                 cli.derivepassphrase_vault,
785 785
                 options if service else [*options, '--', DUMMY_SERVICE],
786 786
                 input=input,
787 787
                 catch_exceptions=False,
788 788
             )
789
-            result = tests.ReadableResult.parse(_result)
789
+            result = tests.ReadableResult.parse(result_)
790 790
             if service is not None:
791 791
                 err_msg = (
792 792
                     ' requires a SERVICE'
793 793
                     if service
794 794
                     else ' does not take a SERVICE argument'
795 795
                 )
796
-                assert result.error_exit(
797
-                    error=err_msg
798
-                ), 'expected error exit and known error message'
796
+                assert result.error_exit(error=err_msg), (
797
+                    'expected error exit and known error message'
798
+                )
799 799
             else:
800
-                assert result.clean_exit(
801
-                    empty_stderr=True
802
-                ), 'expected clean exit'
800
+                assert result.clean_exit(empty_stderr=True), (
801
+                    'expected clean exit'
802
+                )
803 803
         if check_success:
804 804
             with tests.isolated_vault_config(
805 805
                 monkeypatch=monkeypatch,
... ...
@@ -809,13 +809,13 @@ class TestCLI:
809 809
                 monkeypatch.setattr(
810 810
                     cli, '_prompt_for_passphrase', tests.auto_prompt
811 811
                 )
812
-                _result = runner.invoke(
812
+                result_ = runner.invoke(
813 813
                     cli.derivepassphrase_vault,
814 814
                     [*options, '--', DUMMY_SERVICE] if service else options,
815 815
                     input=input,
816 816
                     catch_exceptions=False,
817 817
                 )
818
-                result = tests.ReadableResult.parse(_result)
818
+                result = tests.ReadableResult.parse(result_)
819 819
             assert result.clean_exit(empty_stderr=True), 'expected clean exit'
820 820
 
821 821
     def test_211a_empty_service_name_causes_warning(
... ...
@@ -837,34 +837,34 @@ class TestCLI:
837 837
             runner=runner,
838 838
             vault_config={'services': {}},
839 839
         ):
840
-            _result = runner.invoke(
840
+            result_ = runner.invoke(
841 841
                 cli.derivepassphrase_vault,
842 842
                 ['--config', '--length=30', '--', ''],
843 843
                 catch_exceptions=False,
844 844
             )
845
-            result = tests.ReadableResult.parse(_result)
845
+            result = tests.ReadableResult.parse(result_)
846 846
             assert result.clean_exit(empty_stderr=False), 'expected clean exit'
847 847
             assert result.stderr is not None, 'expected known error output'
848
-            assert all(
849
-                map(is_expected_warning, caplog.record_tuples)
850
-            ), 'expected known error output'
848
+            assert all(map(is_expected_warning, caplog.record_tuples)), (
849
+                'expected known error output'
850
+            )
851 851
             assert cli._load_config() == {
852 852
                 'global': {'length': 30},
853 853
                 'services': {},
854 854
             }, 'requested configuration change was not applied'
855 855
             caplog.clear()
856
-            _result = runner.invoke(
856
+            result_ = runner.invoke(
857 857
                 cli.derivepassphrase_vault,
858 858
                 ['--import', '-'],
859 859
                 input=json.dumps({'services': {'': {'length': 40}}}),
860 860
                 catch_exceptions=False,
861 861
             )
862
-            result = tests.ReadableResult.parse(_result)
862
+            result = tests.ReadableResult.parse(result_)
863 863
             assert result.clean_exit(empty_stderr=False), 'expected clean exit'
864 864
             assert result.stderr is not None, 'expected known error output'
865
-            assert all(
866
-                map(is_expected_warning, caplog.record_tuples)
867
-            ), 'expected known error output'
865
+            assert all(map(is_expected_warning, caplog.record_tuples)), (
866
+                'expected known error output'
867
+            )
868 868
             assert cli._load_config() == {
869 869
                 'global': {'length': 30},
870 870
                 'services': {'': {'length': 40}},
... ...
@@ -889,16 +889,16 @@ class TestCLI:
889 889
             monkeypatch=monkeypatch,
890 890
             runner=runner,
891 891
         ):
892
-            _result = runner.invoke(
892
+            result_ = runner.invoke(
893 893
                 cli.derivepassphrase_vault,
894 894
                 [*options, '--', DUMMY_SERVICE] if service else options,
895 895
                 input=DUMMY_PASSPHRASE,
896 896
                 catch_exceptions=False,
897 897
             )
898
-        result = tests.ReadableResult.parse(_result)
899
-        assert result.error_exit(
900
-            error='mutually exclusive with '
901
-        ), 'expected error exit and known error message'
898
+        result = tests.ReadableResult.parse(result_)
899
+        assert result.error_exit(error='mutually exclusive with '), (
900
+            'expected error exit and known error message'
901
+        )
902 902
 
903 903
     @pytest.mark.parametrize(
904 904
         'config',
... ...
@@ -920,7 +920,7 @@ class TestCLI:
920 920
             runner=runner,
921 921
             vault_config={'services': {}},
922 922
         ):
923
-            _result = runner.invoke(
923
+            result_ = runner.invoke(
924 924
                 cli.derivepassphrase_vault,
925 925
                 ['--import', '-'],
926 926
                 input=json.dumps(config),
... ...
@@ -930,7 +930,7 @@ class TestCLI:
930 930
                 cli._config_filename(subsystem='vault'), encoding='UTF-8'
931 931
             ) as infile:
932 932
                 config2 = json.load(infile)
933
-        result = tests.ReadableResult.parse(_result)
933
+        result = tests.ReadableResult.parse(result_)
934 934
         assert result.clean_exit(empty_stderr=False), 'expected clean exit'
935 935
         assert config2 == config, 'config not imported correctly'
936 936
         assert not result.stderr or all(  # pragma: no branch
... ...
@@ -959,7 +959,7 @@ class TestCLI:
959 959
             runner=runner,
960 960
             vault_config={'services': {}},
961 961
         ):
962
-            _result = runner.invoke(
962
+            result_ = runner.invoke(
963 963
                 cli.derivepassphrase_vault,
964 964
                 ['--import', '-'],
965 965
                 input=json.dumps(config),
... ...
@@ -969,7 +969,7 @@ class TestCLI:
969 969
                 cli._config_filename(subsystem='vault'), encoding='UTF-8'
970 970
             ) as infile:
971 971
                 config3 = json.load(infile)
972
-        result = tests.ReadableResult.parse(_result)
972
+        result = tests.ReadableResult.parse(result_)
973 973
         assert result.clean_exit(empty_stderr=False), 'expected clean exit'
974 974
         assert config3 == config2, 'config not imported correctly'
975 975
         assert not result.stderr or all(
... ...
@@ -982,16 +982,16 @@ class TestCLI:
982 982
     ) -> None:
983 983
         runner = click.testing.CliRunner(mix_stderr=False)
984 984
         with tests.isolated_config(monkeypatch=monkeypatch, runner=runner):
985
-            _result = runner.invoke(
985
+            result_ = runner.invoke(
986 986
                 cli.derivepassphrase_vault,
987 987
                 ['--import', '-'],
988 988
                 input='null',
989 989
                 catch_exceptions=False,
990 990
             )
991
-        result = tests.ReadableResult.parse(_result)
992
-        assert result.error_exit(
993
-            error='Invalid vault config'
994
-        ), 'expected error exit and known error message'
991
+        result = tests.ReadableResult.parse(result_)
992
+        assert result.error_exit(error='Invalid vault config'), (
993
+            'expected error exit and known error message'
994
+        )
995 995
 
996 996
     def test_213c_import_bad_config_not_json_data(
997 997
         self,
... ...
@@ -999,16 +999,16 @@ class TestCLI:
999 999
     ) -> None:
1000 1000
         runner = click.testing.CliRunner(mix_stderr=False)
1001 1001
         with tests.isolated_config(monkeypatch=monkeypatch, runner=runner):
1002
-            _result = runner.invoke(
1002
+            result_ = runner.invoke(
1003 1003
                 cli.derivepassphrase_vault,
1004 1004
                 ['--import', '-'],
1005 1005
                 input='This string is not valid JSON.',
1006 1006
                 catch_exceptions=False,
1007 1007
             )
1008
-        result = tests.ReadableResult.parse(_result)
1009
-        assert result.error_exit(
1010
-            error='cannot decode JSON'
1011
-        ), 'expected error exit and known error message'
1008
+        result = tests.ReadableResult.parse(result_)
1009
+        assert result.error_exit(error='cannot decode JSON'), (
1010
+            'expected error exit and known error message'
1011
+        )
1012 1012
 
1013 1013
     def test_213d_import_bad_config_not_a_file(
1014 1014
         self,
... ...
@@ -1025,15 +1025,15 @@ class TestCLI:
1025 1025
             ) as outfile:
1026 1026
                 print('This string is not valid JSON.', file=outfile)
1027 1027
             dname = cli._config_filename(subsystem=None)
1028
-            _result = runner.invoke(
1028
+            result_ = runner.invoke(
1029 1029
                 cli.derivepassphrase_vault,
1030 1030
                 ['--import', os.fsdecode(dname)],
1031 1031
                 catch_exceptions=False,
1032 1032
             )
1033
-        result = tests.ReadableResult.parse(_result)
1034
-        assert result.error_exit(
1035
-            error=os.strerror(errno.EISDIR)
1036
-        ), 'expected error exit and known error message'
1033
+        result = tests.ReadableResult.parse(result_)
1034
+        assert result.error_exit(error=os.strerror(errno.EISDIR)), (
1035
+            'expected error exit and known error message'
1036
+        )
1037 1037
 
1038 1038
     @pytest.mark.parametrize(
1039 1039
         'export_options',
... ...
@@ -1051,7 +1051,7 @@ class TestCLI:
1051 1051
         with tests.isolated_config(monkeypatch=monkeypatch, runner=runner):
1052 1052
             with contextlib.suppress(FileNotFoundError):
1053 1053
                 os.remove(cli._config_filename(subsystem='vault'))
1054
-            _result = runner.invoke(
1054
+            result_ = runner.invoke(
1055 1055
                 # Test parent context navigation by not calling
1056 1056
                 # `cli.derivepassphrase_vault` directly.  Used e.g. in
1057 1057
                 # the `--export-as=sh` section to autoconstruct the
... ...
@@ -1060,7 +1060,7 @@ class TestCLI:
1060 1060
                 ['vault', '--export', '-', *export_options],
1061 1061
                 catch_exceptions=False,
1062 1062
             )
1063
-        result = tests.ReadableResult.parse(_result)
1063
+        result = tests.ReadableResult.parse(result_)
1064 1064
         assert result.clean_exit(empty_stderr=True), 'expected clean exit'
1065 1065
 
1066 1066
     @pytest.mark.parametrize(
... ...
@@ -1079,16 +1079,16 @@ class TestCLI:
1079 1079
         with tests.isolated_vault_config(
1080 1080
             monkeypatch=monkeypatch, runner=runner, vault_config={}
1081 1081
         ):
1082
-            _result = runner.invoke(
1082
+            result_ = runner.invoke(
1083 1083
                 cli.derivepassphrase_vault,
1084 1084
                 ['--export', '-', *export_options],
1085 1085
                 input='null',
1086 1086
                 catch_exceptions=False,
1087 1087
             )
1088
-        result = tests.ReadableResult.parse(_result)
1089
-        assert result.error_exit(
1090
-            error='Cannot load vault settings:'
1091
-        ), 'expected error exit and known error message'
1088
+        result = tests.ReadableResult.parse(result_)
1089
+        assert result.error_exit(error='Cannot load vault settings:'), (
1090
+            'expected error exit and known error message'
1091
+        )
1092 1092
 
1093 1093
     @pytest.mark.parametrize(
1094 1094
         'export_options',
... ...
@@ -1107,16 +1107,16 @@ class TestCLI:
1107 1107
             with contextlib.suppress(FileNotFoundError):
1108 1108
                 os.remove(cli._config_filename(subsystem='vault'))
1109 1109
             os.makedirs(cli._config_filename(subsystem='vault'))
1110
-            _result = runner.invoke(
1110
+            result_ = runner.invoke(
1111 1111
                 cli.derivepassphrase_vault,
1112 1112
                 ['--export', '-', *export_options],
1113 1113
                 input='null',
1114 1114
                 catch_exceptions=False,
1115 1115
             )
1116
-        result = tests.ReadableResult.parse(_result)
1117
-        assert result.error_exit(
1118
-            error='Cannot load vault settings:'
1119
-        ), 'expected error exit and known error message'
1116
+        result = tests.ReadableResult.parse(result_)
1117
+        assert result.error_exit(error='Cannot load vault settings:'), (
1118
+            'expected error exit and known error message'
1119
+        )
1120 1120
 
1121 1121
     @pytest.mark.parametrize(
1122 1122
         'export_options',
... ...
@@ -1133,16 +1133,16 @@ class TestCLI:
1133 1133
         runner = click.testing.CliRunner(mix_stderr=False)
1134 1134
         with tests.isolated_config(monkeypatch=monkeypatch, runner=runner):
1135 1135
             dname = cli._config_filename(subsystem=None)
1136
-            _result = runner.invoke(
1136
+            result_ = runner.invoke(
1137 1137
                 cli.derivepassphrase_vault,
1138 1138
                 ['--export', os.fsdecode(dname), *export_options],
1139 1139
                 input='null',
1140 1140
                 catch_exceptions=False,
1141 1141
             )
1142
-        result = tests.ReadableResult.parse(_result)
1143
-        assert result.error_exit(
1144
-            error='Cannot export vault settings:'
1145
-        ), 'expected error exit and known error message'
1142
+        result = tests.ReadableResult.parse(result_)
1143
+        assert result.error_exit(error='Cannot export vault settings:'), (
1144
+            'expected error exit and known error message'
1145
+        )
1146 1146
 
1147 1147
     @pytest.mark.parametrize(
1148 1148
         'export_options',
... ...
@@ -1162,18 +1162,18 @@ class TestCLI:
1162 1162
                 shutil.rmtree('.derivepassphrase')
1163 1163
             with open('.derivepassphrase', 'w', encoding='UTF-8') as outfile:
1164 1164
                 print('Obstruction!!', file=outfile)
1165
-            _result = runner.invoke(
1165
+            result_ = runner.invoke(
1166 1166
                 cli.derivepassphrase_vault,
1167 1167
                 ['--export', '-', *export_options],
1168 1168
                 input='null',
1169 1169
                 catch_exceptions=False,
1170 1170
             )
1171
-        result = tests.ReadableResult.parse(_result)
1171
+        result = tests.ReadableResult.parse(result_)
1172 1172
         assert result.error_exit(
1173 1173
             error='Cannot load vault settings:'
1174
-        ) or result.error_exit(
1175
-            error='Cannot load user config:'
1176
-        ), 'expected error exit and known error message'
1174
+        ) or result.error_exit(error='Cannot load user config:'), (
1175
+            'expected error exit and known error message'
1176
+        )
1177 1177
 
1178 1178
     def test_220_edit_notes_successfully(
1179 1179
         self, monkeypatch: pytest.MonkeyPatch
... ...
@@ -1190,12 +1190,12 @@ contents go here
1190 1190
             vault_config={'global': {'phrase': 'abc'}, 'services': {}},
1191 1191
         ):
1192 1192
             monkeypatch.setattr(click, 'edit', lambda *a, **kw: edit_result)  # noqa: ARG005
1193
-            _result = runner.invoke(
1193
+            result_ = runner.invoke(
1194 1194
                 cli.derivepassphrase_vault,
1195 1195
                 ['--notes', '--', 'sv'],
1196 1196
                 catch_exceptions=False,
1197 1197
             )
1198
-            result = tests.ReadableResult.parse(_result)
1198
+            result = tests.ReadableResult.parse(result_)
1199 1199
             assert result.clean_exit(empty_stderr=True), 'expected clean exit'
1200 1200
             with open(
1201 1201
                 cli._config_filename(subsystem='vault'), encoding='UTF-8'
... ...
@@ -1216,12 +1216,12 @@ contents go here
1216 1216
             vault_config={'global': {'phrase': 'abc'}, 'services': {}},
1217 1217
         ):
1218 1218
             monkeypatch.setattr(click, 'edit', lambda *a, **kw: None)  # noqa: ARG005
1219
-            _result = runner.invoke(
1219
+            result_ = runner.invoke(
1220 1220
                 cli.derivepassphrase_vault,
1221 1221
                 ['--notes', '--', 'sv'],
1222 1222
                 catch_exceptions=False,
1223 1223
             )
1224
-            result = tests.ReadableResult.parse(_result)
1224
+            result = tests.ReadableResult.parse(result_)
1225 1225
             assert result.clean_exit(empty_stderr=True), 'expected clean exit'
1226 1226
             with open(
1227 1227
                 cli._config_filename(subsystem='vault'), encoding='UTF-8'
... ...
@@ -1239,12 +1239,12 @@ contents go here
1239 1239
             vault_config={'global': {'phrase': 'abc'}, 'services': {}},
1240 1240
         ):
1241 1241
             monkeypatch.setattr(click, 'edit', lambda *a, **kw: 'long\ntext')  # noqa: ARG005
1242
-            _result = runner.invoke(
1242
+            result_ = runner.invoke(
1243 1243
                 cli.derivepassphrase_vault,
1244 1244
                 ['--notes', '--', 'sv'],
1245 1245
                 catch_exceptions=False,
1246 1246
             )
1247
-            result = tests.ReadableResult.parse(_result)
1247
+            result = tests.ReadableResult.parse(result_)
1248 1248
             assert result.clean_exit(empty_stderr=True), 'expected clean exit'
1249 1249
             with open(
1250 1250
                 cli._config_filename(subsystem='vault'), encoding='UTF-8'
... ...
@@ -1265,15 +1265,15 @@ contents go here
1265 1265
             vault_config={'global': {'phrase': 'abc'}, 'services': {}},
1266 1266
         ):
1267 1267
             monkeypatch.setattr(click, 'edit', lambda *a, **kw: '\n\n')  # noqa: ARG005
1268
-            _result = runner.invoke(
1268
+            result_ = runner.invoke(
1269 1269
                 cli.derivepassphrase_vault,
1270 1270
                 ['--notes', '--', 'sv'],
1271 1271
                 catch_exceptions=False,
1272 1272
             )
1273
-            result = tests.ReadableResult.parse(_result)
1274
-            assert result.error_exit(
1275
-                error='the user aborted the request'
1276
-            ), 'expected known error message'
1273
+            result = tests.ReadableResult.parse(result_)
1274
+            assert result.error_exit(error='the user aborted the request'), (
1275
+                'expected known error message'
1276
+            )
1277 1277
             with open(
1278 1278
                 cli._config_filename(subsystem='vault'), encoding='UTF-8'
1279 1279
             ) as infile:
... ...
@@ -1338,21 +1338,21 @@ contents go here
1338 1338
             monkeypatch.setattr(
1339 1339
                 cli, '_get_suitable_ssh_keys', tests.suitable_ssh_keys
1340 1340
             )
1341
-            _result = runner.invoke(
1341
+            result_ = runner.invoke(
1342 1342
                 cli.derivepassphrase_vault,
1343 1343
                 ['--config', *command_line],
1344 1344
                 catch_exceptions=False,
1345 1345
                 input=input,
1346 1346
             )
1347
-            result = tests.ReadableResult.parse(_result)
1347
+            result = tests.ReadableResult.parse(result_)
1348 1348
             assert result.clean_exit(), 'expected clean exit'
1349 1349
             with open(
1350 1350
                 cli._config_filename(subsystem='vault'), encoding='UTF-8'
1351 1351
             ) as infile:
1352 1352
                 config = json.load(infile)
1353
-            assert (
1354
-                config == result_config
1355
-            ), 'stored config does not match expectation'
1353
+            assert config == result_config, (
1354
+                'stored config does not match expectation'
1355
+            )
1356 1356
 
1357 1357
     @pytest.mark.parametrize(
1358 1358
         ['command_line', 'input', 'err_text'],
... ...
@@ -1387,16 +1387,16 @@ contents go here
1387 1387
             monkeypatch.setattr(
1388 1388
                 cli, '_get_suitable_ssh_keys', tests.suitable_ssh_keys
1389 1389
             )
1390
-            _result = runner.invoke(
1390
+            result_ = runner.invoke(
1391 1391
                 cli.derivepassphrase_vault,
1392 1392
                 ['--config', *command_line],
1393 1393
                 catch_exceptions=False,
1394 1394
                 input=input,
1395 1395
             )
1396
-        result = tests.ReadableResult.parse(_result)
1397
-        assert result.error_exit(
1398
-            error=err_text
1399
-        ), 'expected error exit and known error message'
1396
+        result = tests.ReadableResult.parse(result_)
1397
+        assert result.error_exit(error=err_text), (
1398
+            'expected error exit and known error message'
1399
+        )
1400 1400
 
1401 1401
     def test_225a_store_config_fail_manual_no_ssh_key_selection(
1402 1402
         self,
... ...
@@ -1414,15 +1414,15 @@ contents go here
1414 1414
                 raise RuntimeError(custom_error)
1415 1415
 
1416 1416
             monkeypatch.setattr(cli, '_select_ssh_key', raiser)
1417
-            _result = runner.invoke(
1417
+            result_ = runner.invoke(
1418 1418
                 cli.derivepassphrase_vault,
1419 1419
                 ['--key', '--config'],
1420 1420
                 catch_exceptions=False,
1421 1421
             )
1422
-        result = tests.ReadableResult.parse(_result)
1423
-        assert result.error_exit(
1424
-            error=custom_error
1425
-        ), 'expected error exit and known error message'
1422
+        result = tests.ReadableResult.parse(result_)
1423
+        assert result.error_exit(error=custom_error), (
1424
+            'expected error exit and known error message'
1425
+        )
1426 1426
 
1427 1427
     def test_225b_store_config_fail_manual_no_ssh_agent(
1428 1428
         self,
... ...
@@ -1437,15 +1437,15 @@ contents go here
1437 1437
             vault_config={'global': {'phrase': 'abc'}, 'services': {}},
1438 1438
         ):
1439 1439
             monkeypatch.delenv('SSH_AUTH_SOCK', raising=False)
1440
-            _result = runner.invoke(
1440
+            result_ = runner.invoke(
1441 1441
                 cli.derivepassphrase_vault,
1442 1442
                 ['--key', '--config'],
1443 1443
                 catch_exceptions=False,
1444 1444
             )
1445
-        result = tests.ReadableResult.parse(_result)
1446
-        assert result.error_exit(
1447
-            error='Cannot find any running SSH agent'
1448
-        ), 'expected error exit and known error message'
1445
+        result = tests.ReadableResult.parse(result_)
1446
+        assert result.error_exit(error='Cannot find any running SSH agent'), (
1447
+            'expected error exit and known error message'
1448
+        )
1449 1449
 
1450 1450
     def test_225c_store_config_fail_manual_bad_ssh_agent_connection(
1451 1451
         self,
... ...
@@ -1458,15 +1458,15 @@ contents go here
1458 1458
             vault_config={'global': {'phrase': 'abc'}, 'services': {}},
1459 1459
         ):
1460 1460
             monkeypatch.setenv('SSH_AUTH_SOCK', os.getcwd())
1461
-            _result = runner.invoke(
1461
+            result_ = runner.invoke(
1462 1462
                 cli.derivepassphrase_vault,
1463 1463
                 ['--key', '--config'],
1464 1464
                 catch_exceptions=False,
1465 1465
             )
1466
-        result = tests.ReadableResult.parse(_result)
1467
-        assert result.error_exit(
1468
-            error='Cannot connect to the SSH agent'
1469
-        ), 'expected error exit and known error message'
1466
+        result = tests.ReadableResult.parse(result_)
1467
+        assert result.error_exit(error='Cannot connect to the SSH agent'), (
1468
+            'expected error exit and known error message'
1469
+        )
1470 1470
 
1471 1471
     @pytest.mark.parametrize('try_race_free_implementation', [True, False])
1472 1472
     def test_225d_store_config_fail_manual_read_only_file(
... ...
@@ -1484,15 +1484,15 @@ contents go here
1484 1484
                 cli._config_filename(subsystem='vault'),
1485 1485
                 try_race_free_implementation=try_race_free_implementation,
1486 1486
             )
1487
-            _result = runner.invoke(
1487
+            result_ = runner.invoke(
1488 1488
                 cli.derivepassphrase_vault,
1489 1489
                 ['--config', '--length=15', '--', DUMMY_SERVICE],
1490 1490
                 catch_exceptions=False,
1491 1491
             )
1492
-        result = tests.ReadableResult.parse(_result)
1493
-        assert result.error_exit(
1494
-            error='Cannot store vault settings:'
1495
-        ), 'expected error exit and known error message'
1492
+        result = tests.ReadableResult.parse(result_)
1493
+        assert result.error_exit(error='Cannot store vault settings:'), (
1494
+            'expected error exit and known error message'
1495
+        )
1496 1496
 
1497 1497
     def test_225e_store_config_fail_manual_custom_error(
1498 1498
         self,
... ...
@@ -1511,15 +1511,15 @@ contents go here
1511 1511
                 raise RuntimeError(custom_error)
1512 1512
 
1513 1513
             monkeypatch.setattr(cli, '_save_config', raiser)
1514
-            _result = runner.invoke(
1514
+            result_ = runner.invoke(
1515 1515
                 cli.derivepassphrase_vault,
1516 1516
                 ['--config', '--length=15', '--', DUMMY_SERVICE],
1517 1517
                 catch_exceptions=False,
1518 1518
             )
1519
-        result = tests.ReadableResult.parse(_result)
1520
-        assert result.error_exit(
1521
-            error=custom_error
1522
-        ), 'expected error exit and known error message'
1519
+        result = tests.ReadableResult.parse(result_)
1520
+        assert result.error_exit(error=custom_error), (
1521
+            'expected error exit and known error message'
1522
+        )
1523 1523
 
1524 1524
     def test_225f_store_config_fail_unset_and_set_same_settings(
1525 1525
         self,
... ...
@@ -1531,7 +1531,7 @@ contents go here
1531 1531
             runner=runner,
1532 1532
             vault_config={'global': {'phrase': 'abc'}, 'services': {}},
1533 1533
         ):
1534
-            _result = runner.invoke(
1534
+            result_ = runner.invoke(
1535 1535
                 cli.derivepassphrase_vault,
1536 1536
                 [
1537 1537
                     '--config',
... ...
@@ -1542,7 +1542,7 @@ contents go here
1542 1542
                 ],
1543 1543
                 catch_exceptions=False,
1544 1544
             )
1545
-        result = tests.ReadableResult.parse(_result)
1545
+        result = tests.ReadableResult.parse(result_)
1546 1546
         assert result.error_exit(
1547 1547
             error='Attempted to unset and set --length at the same time.'
1548 1548
         ), 'expected error exit and known error message'
... ...
@@ -1567,15 +1567,15 @@ contents go here
1567 1567
                 return []
1568 1568
 
1569 1569
             monkeypatch.setattr(ssh_agent.SSHAgentClient, 'list_keys', func)
1570
-            _result = runner.invoke(
1570
+            result_ = runner.invoke(
1571 1571
                 cli.derivepassphrase_vault,
1572 1572
                 ['--key', '--config'],
1573 1573
                 catch_exceptions=False,
1574 1574
             )
1575
-        result = tests.ReadableResult.parse(_result)
1576
-        assert result.error_exit(
1577
-            error='no keys suitable'
1578
-        ), 'expected error exit and known error message'
1575
+        result = tests.ReadableResult.parse(result_)
1576
+        assert result.error_exit(error='no keys suitable'), (
1577
+            'expected error exit and known error message'
1578
+        )
1579 1579
 
1580 1580
     def test_225h_store_config_fail_manual_ssh_agent_runtime_error(
1581 1581
         self,
... ...
@@ -1594,12 +1594,12 @@ contents go here
1594 1594
                 raise ssh_agent.TrailingDataError()
1595 1595
 
1596 1596
             monkeypatch.setattr(ssh_agent.SSHAgentClient, 'list_keys', raiser)
1597
-            _result = runner.invoke(
1597
+            result_ = runner.invoke(
1598 1598
                 cli.derivepassphrase_vault,
1599 1599
                 ['--key', '--config'],
1600 1600
                 catch_exceptions=False,
1601 1601
             )
1602
-        result = tests.ReadableResult.parse(_result)
1602
+        result = tests.ReadableResult.parse(result_)
1603 1603
         assert result.error_exit(
1604 1604
             error='violates the communications protocol.'
1605 1605
         ), 'expected error exit and known error message'
... ...
@@ -1623,15 +1623,15 @@ contents go here
1623 1623
                 )
1624 1624
 
1625 1625
             monkeypatch.setattr(ssh_agent.SSHAgentClient, 'list_keys', func)
1626
-            _result = runner.invoke(
1626
+            result_ = runner.invoke(
1627 1627
                 cli.derivepassphrase_vault,
1628 1628
                 ['--key', '--config'],
1629 1629
                 catch_exceptions=False,
1630 1630
             )
1631
-        result = tests.ReadableResult.parse(_result)
1632
-        assert result.error_exit(
1633
-            error='refused to'
1634
-        ), 'expected error exit and known error message'
1631
+        result = tests.ReadableResult.parse(result_)
1632
+        assert result.error_exit(error='refused to'), (
1633
+            'expected error exit and known error message'
1634
+        )
1635 1635
 
1636 1636
     def test_226_no_arguments(self, monkeypatch: pytest.MonkeyPatch) -> None:
1637 1637
         runner = click.testing.CliRunner(mix_stderr=False)
... ...
@@ -1639,10 +1639,10 @@ contents go here
1639 1639
             monkeypatch=monkeypatch,
1640 1640
             runner=runner,
1641 1641
         ):
1642
-            _result = runner.invoke(
1642
+            result_ = runner.invoke(
1643 1643
                 cli.derivepassphrase_vault, [], catch_exceptions=False
1644 1644
             )
1645
-        result = tests.ReadableResult.parse(_result)
1645
+        result = tests.ReadableResult.parse(result_)
1646 1646
         assert result.error_exit(
1647 1647
             error='Deriving a passphrase requires a SERVICE'
1648 1648
         ), 'expected error exit and known error message'
... ...
@@ -1655,15 +1655,15 @@ contents go here
1655 1655
             monkeypatch=monkeypatch,
1656 1656
             runner=runner,
1657 1657
         ):
1658
-            _result = runner.invoke(
1658
+            result_ = runner.invoke(
1659 1659
                 cli.derivepassphrase_vault,
1660 1660
                 ['--', DUMMY_SERVICE],
1661 1661
                 catch_exceptions=False,
1662 1662
             )
1663
-        result = tests.ReadableResult.parse(_result)
1664
-        assert result.error_exit(
1665
-            error='No passphrase or key was given'
1666
-        ), 'expected error exit and known error message'
1663
+        result = tests.ReadableResult.parse(result_)
1664
+        assert result.error_exit(error='No passphrase or key was given'), (
1665
+            'expected error exit and known error message'
1666
+        )
1667 1667
 
1668 1668
     def test_230_config_directory_nonexistant(
1669 1669
         self, monkeypatch: pytest.MonkeyPatch
... ...
@@ -1684,17 +1684,17 @@ contents go here
1684 1684
                 return real_os_makedirs(*args, **kwargs)
1685 1685
 
1686 1686
             monkeypatch.setattr(os, 'makedirs', makedirs)
1687
-            _result = runner.invoke(
1687
+            result_ = runner.invoke(
1688 1688
                 cli.derivepassphrase_vault,
1689 1689
                 ['--config', '-p'],
1690 1690
                 catch_exceptions=False,
1691 1691
                 input='abc\n',
1692 1692
             )
1693
-            result = tests.ReadableResult.parse(_result)
1693
+            result = tests.ReadableResult.parse(result_)
1694 1694
             assert result.clean_exit(), 'expected clean exit'
1695
-            assert (
1696
-                result.stderr == 'Passphrase:'
1697
-            ), 'program unexpectedly failed?!'
1695
+            assert result.stderr == 'Passphrase:', (
1696
+                'program unexpectedly failed?!'
1697
+            )
1698 1698
             assert os_makedirs_called, 'os.makedirs has not been called?!'
1699 1699
             with open(
1700 1700
                 cli._config_filename(subsystem='vault'), encoding='UTF-8'
... ...
@@ -1714,7 +1714,7 @@ contents go here
1714 1714
             monkeypatch=monkeypatch,
1715 1715
             runner=runner,
1716 1716
         ):
1717
-            _save_config = cli._save_config
1717
+            save_config_ = cli._save_config
1718 1718
 
1719 1719
             def obstruct_config_saving(*args: Any, **kwargs: Any) -> Any:
1720 1720
                 with contextlib.suppress(FileNotFoundError):
... ...
@@ -1723,20 +1723,20 @@ contents go here
1723 1723
                     '.derivepassphrase', 'w', encoding='UTF-8'
1724 1724
                 ) as outfile:
1725 1725
                     print('Obstruction!!', file=outfile)
1726
-                monkeypatch.setattr(cli, '_save_config', _save_config)
1727
-                return _save_config(*args, **kwargs)
1726
+                monkeypatch.setattr(cli, '_save_config', save_config_)
1727
+                return save_config_(*args, **kwargs)
1728 1728
 
1729 1729
             monkeypatch.setattr(cli, '_save_config', obstruct_config_saving)
1730
-            _result = runner.invoke(
1730
+            result_ = runner.invoke(
1731 1731
                 cli.derivepassphrase_vault,
1732 1732
                 ['--config', '-p'],
1733 1733
                 catch_exceptions=False,
1734 1734
                 input='abc\n',
1735 1735
             )
1736
-            result = tests.ReadableResult.parse(_result)
1737
-            assert result.error_exit(
1738
-                error='Cannot store vault settings:'
1739
-            ), 'expected error exit and known error message'
1736
+            result = tests.ReadableResult.parse(result_)
1737
+            assert result.error_exit(error='Cannot store vault settings:'), (
1738
+                'expected error exit and known error message'
1739
+            )
1740 1740
 
1741 1741
     def test_230b_store_config_custom_error(
1742 1742
         self, monkeypatch: pytest.MonkeyPatch
... ...
@@ -1753,16 +1753,16 @@ contents go here
1753 1753
                 raise RuntimeError(custom_error)
1754 1754
 
1755 1755
             monkeypatch.setattr(cli, '_save_config', raiser)
1756
-            _result = runner.invoke(
1756
+            result_ = runner.invoke(
1757 1757
                 cli.derivepassphrase_vault,
1758 1758
                 ['--config', '-p'],
1759 1759
                 catch_exceptions=False,
1760 1760
                 input='abc\n',
1761 1761
             )
1762
-            result = tests.ReadableResult.parse(_result)
1763
-            assert result.error_exit(
1764
-                error=custom_error
1765
-            ), 'expected error exit and known error message'
1762
+            result = tests.ReadableResult.parse(result_)
1763
+            assert result.error_exit(error=custom_error), (
1764
+                'expected error exit and known error message'
1765
+            )
1766 1766
 
1767 1767
     @pytest.mark.parametrize(
1768 1768
         ['main_config', 'command_line', 'input', 'warning_message'],
... ...
@@ -1881,17 +1881,17 @@ contents go here
1881 1881
             },
1882 1882
             main_config_str=main_config,
1883 1883
         ):
1884
-            _result = runner.invoke(
1884
+            result_ = runner.invoke(
1885 1885
                 cli.derivepassphrase_vault,
1886 1886
                 ['--debug', *command_line],
1887 1887
                 catch_exceptions=False,
1888 1888
                 input=input,
1889 1889
             )
1890
-        result = tests.ReadableResult.parse(_result)
1890
+        result = tests.ReadableResult.parse(result_)
1891 1891
         assert result.clean_exit(), 'expected clean exit'
1892
-        assert tests.warning_emitted(
1893
-            warning_message, caplog.record_tuples
1894
-        ), 'expected known warning message in stderr'
1892
+        assert tests.warning_emitted(warning_message, caplog.record_tuples), (
1893
+            'expected known warning message in stderr'
1894
+        )
1895 1895
 
1896 1896
     @pytest.mark.parametrize(
1897 1897
         ['main_config', 'command_line', 'input', 'error_message'],
... ...
@@ -1951,19 +1951,19 @@ contents go here
1951 1951
             },
1952 1952
             main_config_str=main_config,
1953 1953
         ):
1954
-            _result = runner.invoke(
1954
+            result_ = runner.invoke(
1955 1955
                 cli.derivepassphrase_vault,
1956 1956
                 command_line,
1957 1957
                 catch_exceptions=False,
1958 1958
                 input=input,
1959 1959
             )
1960
-        result = tests.ReadableResult.parse(_result)
1960
+        result = tests.ReadableResult.parse(result_)
1961 1961
         assert result.error_exit(
1962 1962
             error='The user configuration file is invalid.'
1963 1963
         ), 'expected error exit and known error message'
1964
-        assert result.error_exit(
1965
-            error=error_message
1966
-        ), 'expected error exit and known error message'
1964
+        assert result.error_exit(error=error_message), (
1965
+            'expected error exit and known error message'
1966
+        )
1967 1967
 
1968 1968
     @pytest.mark.parametrize(
1969 1969
         'command_line',
... ...
@@ -1995,13 +1995,13 @@ contents go here
1995 1995
             default-unicode-normalization-form = 'XXX'
1996 1996
             """),
1997 1997
         ):
1998
-            _result = runner.invoke(
1998
+            result_ = runner.invoke(
1999 1999
                 cli.derivepassphrase_vault,
2000 2000
                 command_line,
2001 2001
                 input=DUMMY_PASSPHRASE,
2002 2002
                 catch_exceptions=False,
2003 2003
             )
2004
-            result = tests.ReadableResult.parse(_result)
2004
+            result = tests.ReadableResult.parse(result_)
2005 2005
             assert result.error_exit(
2006 2006
                 error='The user configuration file is invalid.'
2007 2007
             ), 'expected error exit and known error message'
... ...
@@ -2025,16 +2025,16 @@ contents go here
2025 2025
             This file is not valid TOML.
2026 2026
             """),
2027 2027
         ):
2028
-            _result = runner.invoke(
2028
+            result_ = runner.invoke(
2029 2029
                 cli.derivepassphrase_vault,
2030 2030
                 ['--phrase', '--', DUMMY_SERVICE],
2031 2031
                 input=DUMMY_PASSPHRASE,
2032 2032
                 catch_exceptions=False,
2033 2033
             )
2034
-            result = tests.ReadableResult.parse(_result)
2035
-            assert result.error_exit(
2036
-                error='Cannot load user config:'
2037
-            ), 'expected error exit and known error message'
2034
+            result = tests.ReadableResult.parse(result_)
2035
+            assert result.error_exit(error='Cannot load user config:'), (
2036
+                'expected error exit and known error message'
2037
+            )
2038 2038
 
2039 2039
     def test_400_missing_af_unix_support(
2040 2040
         self,
... ...
@@ -2050,12 +2050,12 @@ contents go here
2050 2050
                 'SSH_AUTH_SOCK', "the value doesn't even matter"
2051 2051
             )
2052 2052
             monkeypatch.delattr(socket, 'AF_UNIX', raising=False)
2053
-            _result = runner.invoke(
2053
+            result_ = runner.invoke(
2054 2054
                 cli.derivepassphrase_vault,
2055 2055
                 ['--key', '--config'],
2056 2056
                 catch_exceptions=False,
2057 2057
             )
2058
-        result = tests.ReadableResult.parse(_result)
2058
+        result = tests.ReadableResult.parse(result_)
2059 2059
         assert result.error_exit(
2060 2060
             error='does not support UNIX domain sockets'
2061 2061
         ), 'expected error exit and known error message'
... ...
@@ -2141,8 +2141,8 @@ class TestCLIUtils:
2141 2141
             click.echo('(Note: Vikings strictly optional.)')
2142 2142
 
2143 2143
         runner = click.testing.CliRunner(mix_stderr=True)
2144
-        _result = runner.invoke(driver, [], input='9')
2145
-        result = tests.ReadableResult.parse(_result)
2144
+        result_ = runner.invoke(driver, [], input='9')
2145
+        result = tests.ReadableResult.parse(result_)
2146 2146
         assert result.clean_exit(
2147 2147
             output="""\
2148 2148
 Our menu:
... ...
@@ -2161,13 +2161,13 @@ A fine choice: Spam, spam, spam, spam, spam, spam, baked beans, spam, spam, spam
2161 2161
 (Note: Vikings strictly optional.)
2162 2162
 """
2163 2163
         ), 'expected clean exit'
2164
-        _result = runner.invoke(
2164
+        result_ = runner.invoke(
2165 2165
             driver, ['--heading='], input='', catch_exceptions=True
2166 2166
         )
2167
-        result = tests.ReadableResult.parse(_result)
2168
-        assert result.error_exit(
2169
-            error=IndexError
2170
-        ), 'expected error exit and known error type'
2167
+        result = tests.ReadableResult.parse(result_)
2168
+        assert result.error_exit(error=IndexError), (
2169
+            'expected error exit and known error type'
2170
+        )
2171 2171
         assert (
2172 2172
             result.output
2173 2173
             == """\
... ...
@@ -2201,10 +2201,10 @@ Your selection? (1-10, leave empty to abort):\x20
2201 2201
                 click.echo('Great!')
2202 2202
 
2203 2203
         runner = click.testing.CliRunner(mix_stderr=True)
2204
-        _result = runner.invoke(
2204
+        result_ = runner.invoke(
2205 2205
             driver, ['Will replace with spam. Confirm, y/n?'], input='y'
2206 2206
         )
2207
-        result = tests.ReadableResult.parse(_result)
2207
+        result = tests.ReadableResult.parse(result_)
2208 2208
         assert result.clean_exit(
2209 2209
             output="""\
2210 2210
 [1] baked beans
... ...
@@ -2212,15 +2212,15 @@ Will replace with spam. Confirm, y/n? y
2212 2212
 Great!
2213 2213
 """
2214 2214
         ), 'expected clean exit'
2215
-        _result = runner.invoke(
2215
+        result_ = runner.invoke(
2216 2216
             driver,
2217 2217
             ['Will replace with spam, okay? (Please say "y" or "n".)'],
2218 2218
             input='',
2219 2219
         )
2220
-        result = tests.ReadableResult.parse(_result)
2221
-        assert result.error_exit(
2222
-            error=IndexError
2223
-        ), 'expected error exit and known error type'
2220
+        result = tests.ReadableResult.parse(result_)
2221
+        assert result.error_exit(error=IndexError), (
2222
+            'expected error exit and known error type'
2223
+        )
2224 2224
         assert (
2225 2225
             result.output
2226 2226
             == """\
... ...
@@ -2370,8 +2370,8 @@ Boo.
2370 2370
             monkeypatch=monkeypatch,
2371 2371
             vault_config={'services': {}},
2372 2372
         ):
2373
-            for _result in vault_config_exporter_shell_interpreter(script):
2374
-                result = tests.ReadableResult.parse(_result)
2373
+            for result_ in vault_config_exporter_shell_interpreter(script):
2374
+                result = tests.ReadableResult.parse(result_)
2375 2375
                 assert result.clean_exit()
2376 2376
             assert cli._load_config() == config
2377 2377
 
... ...
@@ -2591,15 +2591,15 @@ Boo.
2591 2591
                 runner=runner,
2592 2592
                 vault_config=start_config,
2593 2593
             ):
2594
-                _result = runner.invoke(
2594
+                result_ = runner.invoke(
2595 2595
                     cli.derivepassphrase_vault,
2596 2596
                     command_line,
2597 2597
                     catch_exceptions=False,
2598 2598
                 )
2599
-                result = tests.ReadableResult.parse(_result)
2600
-                assert result.clean_exit(
2601
-                    empty_stderr=True
2602
-                ), 'expected clean exit'
2599
+                result = tests.ReadableResult.parse(result_)
2600
+                assert result.clean_exit(empty_stderr=True), (
2601
+                    'expected clean exit'
2602
+                )
2603 2603
                 with open(
2604 2604
                     cli._config_filename(subsystem='vault'), encoding='UTF-8'
2605 2605
                 ) as infile:
... ...
@@ -2660,9 +2660,9 @@ Boo.
2660 2660
             except Exception as e:  # noqa: BLE001 # pragma: no cover
2661 2661
                 exception = e
2662 2662
             finally:
2663
-                assert (
2664
-                    exception is None
2665
-                ), 'exception querying suitable SSH keys'
2663
+                assert exception is None, (
2664
+                    'exception querying suitable SSH keys'
2665
+                )
2666 2666
 
2667 2667
     def test_400_key_to_phrase(
2668 2668
         self,
... ...
@@ -2755,10 +2755,10 @@ class TestCLITransition:
2755 2755
             monkeypatch=monkeypatch,
2756 2756
             runner=runner,
2757 2757
         ):
2758
-            _result = runner.invoke(
2758
+            result_ = runner.invoke(
2759 2759
                 cli.derivepassphrase, ['--help'], catch_exceptions=False
2760 2760
             )
2761
-            result = tests.ReadableResult.parse(_result)
2761
+            result = tests.ReadableResult.parse(result_)
2762 2762
         assert result.clean_exit(
2763 2763
             empty_stderr=True, output='currently implemented subcommands'
2764 2764
         ), 'expected clean exit, and known help text'
... ...
@@ -2771,12 +2771,12 @@ class TestCLITransition:
2771 2771
             monkeypatch=monkeypatch,
2772 2772
             runner=runner,
2773 2773
         ):
2774
-            _result = runner.invoke(
2774
+            result_ = runner.invoke(
2775 2775
                 cli.derivepassphrase,
2776 2776
                 ['export', '--help'],
2777 2777
                 catch_exceptions=False,
2778 2778
             )
2779
-            result = tests.ReadableResult.parse(_result)
2779
+            result = tests.ReadableResult.parse(result_)
2780 2780
         assert result.clean_exit(
2781 2781
             empty_stderr=True, output='only available subcommand'
2782 2782
         ), 'expected clean exit, and known help text'
... ...
@@ -2789,12 +2789,12 @@ class TestCLITransition:
2789 2789
             monkeypatch=monkeypatch,
2790 2790
             runner=runner,
2791 2791
         ):
2792
-            _result = runner.invoke(
2792
+            result_ = runner.invoke(
2793 2793
                 cli.derivepassphrase,
2794 2794
                 ['export', 'vault', '--help'],
2795 2795
                 catch_exceptions=False,
2796 2796
             )
2797
-            result = tests.ReadableResult.parse(_result)
2797
+            result = tests.ReadableResult.parse(result_)
2798 2798
         assert result.clean_exit(
2799 2799
             empty_stderr=True, output='Export a vault-native configuration'
2800 2800
         ), 'expected clean exit, and known help text'
... ...
@@ -2807,12 +2807,12 @@ class TestCLITransition:
2807 2807
             monkeypatch=monkeypatch,
2808 2808
             runner=runner,
2809 2809
         ):
2810
-            _result = runner.invoke(
2810
+            result_ = runner.invoke(
2811 2811
                 cli.derivepassphrase,
2812 2812
                 ['vault', '--help'],
2813 2813
                 catch_exceptions=False,
2814 2814
             )
2815
-            result = tests.ReadableResult.parse(_result)
2815
+            result = tests.ReadableResult.parse(result_)
2816 2816
         assert result.clean_exit(
2817 2817
             empty_stderr=True, output='Passphrase generation:\n'
2818 2818
         ), 'expected clean exit, and option groups in help text'
... ...
@@ -2963,11 +2963,11 @@ class TestCLITransition:
2963 2963
             vault_key=tests.VAULT_MASTER_KEY,
2964 2964
         ):
2965 2965
             monkeypatch.setenv('VAULT_KEY', tests.VAULT_MASTER_KEY)
2966
-            _result = runner.invoke(
2966
+            result_ = runner.invoke(
2967 2967
                 cli.derivepassphrase,
2968 2968
                 ['export', 'VAULT_PATH'],
2969 2969
             )
2970
-        result = tests.ReadableResult.parse(_result)
2970
+        result = tests.ReadableResult.parse(result_)
2971 2971
         assert result.clean_exit(empty_stderr=False), 'expected clean exit'
2972 2972
         assert tests.deprecation_warning_emitted(
2973 2973
             'A subcommand will be required here in v1.0', caplog.record_tuples
... ...
@@ -2988,20 +2988,20 @@ class TestCLITransition:
2988 2988
             monkeypatch=monkeypatch,
2989 2989
             runner=runner,
2990 2990
         ):
2991
-            _result = runner.invoke(
2991
+            result_ = runner.invoke(
2992 2992
                 cli.derivepassphrase,
2993 2993
                 ['export'],
2994 2994
             )
2995
-        result = tests.ReadableResult.parse(_result)
2995
+        result = tests.ReadableResult.parse(result_)
2996 2996
         assert tests.deprecation_warning_emitted(
2997 2997
             'A subcommand will be required here in v1.0', caplog.record_tuples
2998 2998
         )
2999 2999
         assert tests.deprecation_warning_emitted(
3000 3000
             'Defaulting to subcommand "vault"', caplog.record_tuples
3001 3001
         )
3002
-        assert result.error_exit(
3003
-            error="Missing argument 'PATH'"
3004
-        ), 'expected error exit and known error type'
3002
+        assert result.error_exit(error="Missing argument 'PATH'"), (
3003
+            'expected error exit and known error type'
3004
+        )
3005 3005
 
3006 3006
     @pytest.mark.parametrize(
3007 3007
         'charset_name', ['lower', 'upper', 'number', 'space', 'dash', 'symbol']
... ...
@@ -3020,13 +3020,13 @@ class TestCLITransition:
3020 3020
             monkeypatch=monkeypatch,
3021 3021
             runner=runner,
3022 3022
         ):
3023
-            _result = runner.invoke(
3023
+            result_ = runner.invoke(
3024 3024
                 cli.derivepassphrase,
3025 3025
                 [option, '0', '-p', '--', DUMMY_SERVICE],
3026 3026
                 input=DUMMY_PASSPHRASE,
3027 3027
                 catch_exceptions=False,
3028 3028
             )
3029
-            result = tests.ReadableResult.parse(_result)
3029
+            result = tests.ReadableResult.parse(result_)
3030 3030
         assert result.clean_exit(empty_stderr=False), 'expected clean exit'
3031 3031
         assert tests.deprecation_warning_emitted(
3032 3032
             'A subcommand will be required here in v1.0', caplog.record_tuples
... ...
@@ -3035,9 +3035,9 @@ class TestCLITransition:
3035 3035
             'Defaulting to subcommand "vault"', caplog.record_tuples
3036 3036
         )
3037 3037
         for c in charset:
3038
-            assert (
3039
-                c not in result.output
3040
-            ), f'derived password contains forbidden character {c!r}'
3038
+            assert c not in result.output, (
3039
+                f'derived password contains forbidden character {c!r}'
3040
+            )
3041 3041
 
3042 3042
     def test_211_forward_vault_empty_command_line(
3043 3043
         self,
... ...
@@ -3049,13 +3049,13 @@ class TestCLITransition:
3049 3049
             monkeypatch=monkeypatch,
3050 3050
             runner=runner,
3051 3051
         ):
3052
-            _result = runner.invoke(
3052
+            result_ = runner.invoke(
3053 3053
                 cli.derivepassphrase,
3054 3054
                 [],
3055 3055
                 input=DUMMY_PASSPHRASE,
3056 3056
                 catch_exceptions=False,
3057 3057
             )
3058
-            result = tests.ReadableResult.parse(_result)
3058
+            result = tests.ReadableResult.parse(result_)
3059 3059
         assert tests.deprecation_warning_emitted(
3060 3060
             'A subcommand will be required here in v1.0', caplog.record_tuples
3061 3061
         )
... ...
@@ -3089,12 +3089,12 @@ class TestCLITransition:
3089 3089
                     ),
3090 3090
                     file=fileobj,
3091 3091
                 )
3092
-            _result = runner.invoke(
3092
+            result_ = runner.invoke(
3093 3093
                 cli.derivepassphrase_vault,
3094 3094
                 ['--export', '-'],
3095 3095
                 catch_exceptions=False,
3096 3096
             )
3097
-        result = tests.ReadableResult.parse(_result)
3097
+        result = tests.ReadableResult.parse(result_)
3098 3098
         assert result.clean_exit(), 'expected clean exit'
3099 3099
         assert tests.deprecation_warning_emitted(
3100 3100
             'v0.1-style config file', caplog.record_tuples
... ...
@@ -3134,12 +3134,12 @@ class TestCLITransition:
3134 3134
                 )
3135 3135
 
3136 3136
             monkeypatch.setattr(os, 'replace', raiser)
3137
-            _result = runner.invoke(
3137
+            result_ = runner.invoke(
3138 3138
                 cli.derivepassphrase_vault,
3139 3139
                 ['--export', '-'],
3140 3140
                 catch_exceptions=False,
3141 3141
             )
3142
-        result = tests.ReadableResult.parse(_result)
3142
+        result = tests.ReadableResult.parse(result_)
3143 3143
         assert result.clean_exit(), 'expected clean exit'
3144 3144
         assert tests.deprecation_warning_emitted(
3145 3145
             'v0.1-style config file', caplog.record_tuples
... ...
@@ -3339,7 +3339,7 @@ class ConfigManagementStateMachine(stateful.RuleBasedStateMachine):
3339 3339
         # NOTE: This relies on settings_obj containing only the keys
3340 3340
         # "length", "repeat", "upper", "lower", "number", "space",
3341 3341
         # "dash" and "symbol".
3342
-        _result = self.runner.invoke(
3342
+        result_ = self.runner.invoke(
3343 3343
             cli.derivepassphrase_vault,
3344 3344
             [
3345 3345
                 '--config',
... ...
@@ -3353,7 +3353,7 @@ class ConfigManagementStateMachine(stateful.RuleBasedStateMachine):
3353 3353
             ],
3354 3354
             catch_exceptions=False,
3355 3355
         )
3356
-        result = tests.ReadableResult.parse(_result)
3356
+        result = tests.ReadableResult.parse(result_)
3357 3357
         assert result.clean_exit(empty_stderr=False)
3358 3358
         assert cli._load_config() == config
3359 3359
         return config
... ...
@@ -3390,7 +3390,7 @@ class ConfigManagementStateMachine(stateful.RuleBasedStateMachine):
3390 3390
         # NOTE: This relies on settings_obj containing only the keys
3391 3391
         # "length", "repeat", "upper", "lower", "number", "space",
3392 3392
         # "dash" and "symbol".
3393
-        _result = self.runner.invoke(
3393
+        result_ = self.runner.invoke(
3394 3394
             cli.derivepassphrase_vault,
3395 3395
             [
3396 3396
                 '--config',
... ...
@@ -3405,7 +3405,7 @@ class ConfigManagementStateMachine(stateful.RuleBasedStateMachine):
3405 3405
             + ['--', service],
3406 3406
             catch_exceptions=False,
3407 3407
         )
3408
-        result = tests.ReadableResult.parse(_result)
3408
+        result = tests.ReadableResult.parse(result_)
3409 3409
         assert result.clean_exit(empty_stderr=False)
3410 3410
         assert cli._load_config() == config
3411 3411
         return config
... ...
@@ -3420,13 +3420,13 @@ class ConfigManagementStateMachine(stateful.RuleBasedStateMachine):
3420 3420
     ) -> _types.VaultConfig:
3421 3421
         cli._save_config(config)
3422 3422
         config.pop('global', None)
3423
-        _result = self.runner.invoke(
3423
+        result_ = self.runner.invoke(
3424 3424
             cli.derivepassphrase_vault,
3425 3425
             ['--delete-globals'],
3426 3426
             input='y',
3427 3427
             catch_exceptions=False,
3428 3428
         )
3429
-        result = tests.ReadableResult.parse(_result)
3429
+        result = tests.ReadableResult.parse(result_)
3430 3430
         assert result.clean_exit(empty_stderr=False)
3431 3431
         assert cli._load_config() == config
3432 3432
         return config
... ...
@@ -3449,13 +3449,13 @@ class ConfigManagementStateMachine(stateful.RuleBasedStateMachine):
3449 3449
         config, service = config_and_service
3450 3450
         cli._save_config(config)
3451 3451
         config['services'].pop(service, None)
3452
-        _result = self.runner.invoke(
3452
+        result_ = self.runner.invoke(
3453 3453
             cli.derivepassphrase_vault,
3454 3454
             ['--delete', '--', service],
3455 3455
             input='y',
3456 3456
             catch_exceptions=False,
3457 3457
         )
3458
-        result = tests.ReadableResult.parse(_result)
3458
+        result = tests.ReadableResult.parse(result_)
3459 3459
         assert result.clean_exit(empty_stderr=False)
3460 3460
         assert cli._load_config() == config
3461 3461
         return config
... ...
@@ -3470,13 +3470,13 @@ class ConfigManagementStateMachine(stateful.RuleBasedStateMachine):
3470 3470
     ) -> _types.VaultConfig:
3471 3471
         cli._save_config(config)
3472 3472
         config = {'services': {}}
3473
-        _result = self.runner.invoke(
3473
+        result_ = self.runner.invoke(
3474 3474
             cli.derivepassphrase_vault,
3475 3475
             ['--clear'],
3476 3476
             input='y',
3477 3477
             catch_exceptions=False,
3478 3478
         )
3479
-        result = tests.ReadableResult.parse(_result)
3479
+        result = tests.ReadableResult.parse(result_)
3480 3480
         assert result.clean_exit(empty_stderr=False)
3481 3481
         assert cli._load_config() == config
3482 3482
         return config
... ...
@@ -3500,14 +3500,14 @@ class ConfigManagementStateMachine(stateful.RuleBasedStateMachine):
3500 3500
             else config_to_import
3501 3501
         )
3502 3502
         assert _types.is_vault_config(config)
3503
-        _result = self.runner.invoke(
3503
+        result_ = self.runner.invoke(
3504 3504
             cli.derivepassphrase_vault,
3505 3505
             ['--import', '-']
3506 3506
             + (['--overwrite-existing'] if overwrite else []),
3507 3507
             input=json.dumps(config_to_import),
3508 3508
             catch_exceptions=False,
3509 3509
         )
3510
-        assert tests.ReadableResult.parse(_result).clean_exit(
3510
+        assert tests.ReadableResult.parse(result_).clean_exit(
3511 3511
             empty_stderr=False
3512 3512
         )
3513 3513
         assert cli._load_config() == config
... ...
@@ -4148,19 +4148,19 @@ class TestShellCompletion:
4148 4148
             vault_config=vault_config,
4149 4149
         ):
4150 4150
             if mode == 'config':
4151
-                _result = runner.invoke(
4151
+                result_ = runner.invoke(
4152 4152
                     cli.derivepassphrase_vault,
4153 4153
                     ['--config', '--length=10', '--', key],
4154 4154
                     catch_exceptions=False,
4155 4155
                 )
4156 4156
             else:
4157
-                _result = runner.invoke(
4157
+                result_ = runner.invoke(
4158 4158
                     cli.derivepassphrase_vault,
4159 4159
                     ['--import', '-'],
4160 4160
                     catch_exceptions=False,
4161 4161
                     input=json.dumps(config),
4162 4162
                 )
4163
-            result = tests.ReadableResult.parse(_result)
4163
+            result = tests.ReadableResult.parse(result_)
4164 4164
             assert result.clean_exit(), 'expected clean exit'
4165 4165
             assert tests.warning_emitted(
4166 4166
                 'contains an ASCII control character', caplog.record_tuples
... ...
@@ -46,11 +46,11 @@ class TestCLI:
46 46
             vault_key=tests.VAULT_MASTER_KEY,
47 47
         ):
48 48
             monkeypatch.setenv('VAULT_KEY', tests.VAULT_MASTER_KEY)
49
-            _result = runner.invoke(
49
+            result_ = runner.invoke(
50 50
                 cli.derivepassphrase_export_vault,
51 51
                 ['VAULT_PATH'],
52 52
             )
53
-        result = tests.ReadableResult.parse(_result)
53
+        result = tests.ReadableResult.parse(result_)
54 54
         assert result.clean_exit(empty_stderr=True), 'expected clean exit'
55 55
         assert json.loads(result.output) == tests.VAULT_V03_CONFIG_DATA
56 56
 
... ...
@@ -61,11 +61,11 @@ class TestCLI:
61 61
             runner=runner,
62 62
             vault_config=tests.VAULT_V03_CONFIG,
63 63
         ):
64
-            _result = runner.invoke(
64
+            result_ = runner.invoke(
65 65
                 cli.derivepassphrase_export_vault,
66 66
                 ['-k', tests.VAULT_MASTER_KEY, '.vault'],
67 67
             )
68
-        result = tests.ReadableResult.parse(_result)
68
+        result = tests.ReadableResult.parse(result_)
69 69
         assert result.clean_exit(empty_stderr=True), 'expected clean exit'
70 70
         assert json.loads(result.output) == tests.VAULT_V03_CONFIG_DATA
71 71
 
... ...
@@ -105,11 +105,11 @@ class TestCLI:
105 105
             runner=runner,
106 106
             vault_config=config,
107 107
         ):
108
-            _result = runner.invoke(
108
+            result_ = runner.invoke(
109 109
                 cli.derivepassphrase_export_vault,
110 110
                 ['-f', format, '-k', tests.VAULT_MASTER_KEY, 'VAULT_PATH'],
111 111
             )
112
-        result = tests.ReadableResult.parse(_result)
112
+        result = tests.ReadableResult.parse(result_)
113 113
         assert result.clean_exit(empty_stderr=True), 'expected clean exit'
114 114
         assert json.loads(result.output) == config_data
115 115
 
... ...
@@ -128,11 +128,11 @@ class TestCLI:
128 128
             vault_config=tests.VAULT_V03_CONFIG,
129 129
             vault_key=tests.VAULT_MASTER_KEY,
130 130
         ):
131
-            _result = runner.invoke(
131
+            result_ = runner.invoke(
132 132
                 cli.derivepassphrase_export_vault,
133 133
                 ['does-not-exist.txt'],
134 134
             )
135
-        result = tests.ReadableResult.parse(_result)
135
+        result = tests.ReadableResult.parse(result_)
136 136
         assert result.error_exit(
137 137
             error=(
138 138
                 "Cannot parse 'does-not-exist.txt' "
... ...
@@ -154,11 +154,11 @@ class TestCLI:
154 154
             vault_config='',
155 155
             vault_key=tests.VAULT_MASTER_KEY,
156 156
         ):
157
-            _result = runner.invoke(
157
+            result_ = runner.invoke(
158 158
                 cli.derivepassphrase_export_vault,
159 159
                 ['.vault'],
160 160
             )
161
-        result = tests.ReadableResult.parse(_result)
161
+        result = tests.ReadableResult.parse(result_)
162 162
         assert result.error_exit(
163 163
             error="Cannot parse '.vault' as a valid vault-native config",
164 164
             record_tuples=caplog.record_tuples,
... ...
@@ -177,11 +177,11 @@ class TestCLI:
177 177
             vault_config=tests.VAULT_V02_CONFIG,
178 178
             vault_key=tests.VAULT_MASTER_KEY,
179 179
         ):
180
-            _result = runner.invoke(
180
+            result_ = runner.invoke(
181 181
                 cli.derivepassphrase_export_vault,
182 182
                 ['-f', 'v0.3', '.vault'],
183 183
             )
184
-        result = tests.ReadableResult.parse(_result)
184
+        result = tests.ReadableResult.parse(result_)
185 185
         assert result.error_exit(
186 186
             error="Cannot parse '.vault' as a valid vault-native config",
187 187
             record_tuples=caplog.record_tuples,
... ...
@@ -205,11 +205,11 @@ class TestCLI:
205 205
                 return None
206 206
 
207 207
             monkeypatch.setattr(cli, '_load_data', _load_data)
208
-            _result = runner.invoke(
208
+            result_ = runner.invoke(
209 209
                 cli.derivepassphrase_export_vault,
210 210
                 ['.vault'],
211 211
             )
212
-        result = tests.ReadableResult.parse(_result)
212
+        result = tests.ReadableResult.parse(result_)
213 213
         assert result.error_exit(
214 214
             error='Invalid vault config: ',
215 215
             record_tuples=caplog.record_tuples,
... ...
@@ -353,8 +353,7 @@ class TestStoreroom:
353 353
 
354 354
     def test_404_decrypt_keys_wrong_data_length(self) -> None:
355 355
         payload = (
356
-            b"Any text here, as long as it isn't "
357
-            b'exactly 64 or 96 bytes long.'
356
+            b"Any text here, as long as it isn't exactly 64 or 96 bytes long."
358 357
         )
359 358
         assert len(payload) not in frozenset({
360 359
             2 * storeroom.KEY_SIZE,
... ...
@@ -114,16 +114,16 @@ class Test002CLI:
114 114
             vault_config=tests.VAULT_V03_CONFIG,
115 115
             vault_key=tests.VAULT_MASTER_KEY,
116 116
         ):
117
-            _result = runner.invoke(
117
+            result_ = runner.invoke(
118 118
                 cli.derivepassphrase_export_vault,
119 119
                 ['-f', 'INVALID', 'VAULT_PATH'],
120 120
                 catch_exceptions=False,
121 121
             )
122
-        result = tests.ReadableResult.parse(_result)
122
+        result = tests.ReadableResult.parse(result_)
123 123
         for snippet in ('Invalid value for', '-f', '--format', 'INVALID'):
124
-            assert result.error_exit(
125
-                error=snippet
126
-            ), 'expected error exit and known error message'
124
+            assert result.error_exit(error=snippet), (
125
+                'expected error exit and known error message'
126
+            )
127 127
 
128 128
     @tests.skip_if_cryptography_support
129 129
     @pytest.mark.parametrize(
... ...
@@ -164,12 +164,12 @@ class Test002CLI:
164 164
             vault_config=config,
165 165
             vault_key=key,
166 166
         ):
167
-            _result = runner.invoke(
167
+            result_ = runner.invoke(
168 168
                 cli.derivepassphrase_export_vault,
169 169
                 ['-f', format, 'VAULT_PATH'],
170 170
                 catch_exceptions=False,
171 171
             )
172
-        result = tests.ReadableResult.parse(_result)
172
+        result = tests.ReadableResult.parse(result_)
173 173
         assert result.error_exit(
174 174
             error=tests.CANNOT_LOAD_CRYPTOGRAPHY,
175 175
             record_tuples=caplog.record_tuples,
... ...
@@ -39,9 +39,9 @@ class TestStaticFunctionality:
39 39
         self, public_key: bytes, public_key_data: bytes
40 40
     ) -> None:
41 41
         keydata = base64.b64decode(public_key.split(None, 2)[1])
42
-        assert (
43
-            keydata == public_key_data
44
-        ), "recorded public key data doesn't match"
42
+        assert keydata == public_key_data, (
43
+            "recorded public key data doesn't match"
44
+        )
45 45
 
46 46
     @pytest.mark.parametrize(
47 47
         ['line', 'env_name', 'value'],
... ...
@@ -348,13 +348,13 @@ class TestAgentInteraction:
348 348
             click.echo(base64.standard_b64encode(key).decode('ASCII'))
349 349
 
350 350
         runner = click.testing.CliRunner(mix_stderr=True)
351
-        _result = runner.invoke(
351
+        result_ = runner.invoke(
352 352
             driver,
353 353
             [],
354 354
             input=('yes\n' if single else f'{index}\n'),
355 355
             catch_exceptions=True,
356 356
         )
357
-        result = tests.ReadableResult.parse(_result)
357
+        result = tests.ReadableResult.parse(result_)
358 358
         for snippet in ('Suitable SSH keys:\n', text, f'\n{b64_key}\n'):
359 359
             assert result.clean_exit(output=snippet), 'expected clean exit'
360 360
 
... ...
@@ -99,17 +99,17 @@ def test_200_is_vault_config(test_config: tests.VaultTestConfig) -> None:
99 99
 def test_200a_is_vault_config_smudged(
100 100
     test_config: tests.VaultTestConfig,
101 101
 ) -> None:
102
-    _obj, comment, _ = test_config
103
-    obj = copy.deepcopy(_obj)
102
+    obj_, comment, _ = test_config
103
+    obj = copy.deepcopy(obj_)
104 104
     did_cleanup = _types.clean_up_falsy_vault_config_values(obj)
105 105
     assert _types.is_vault_config(obj) == (not comment), (
106 106
         'failed to complain about: ' + comment
107 107
         if comment
108 108
         else 'failed on valid example'
109 109
     )
110
-    assert did_cleanup is None or bool(did_cleanup) == (
111
-        obj != _obj
112
-    ), 'mismatched report on cleanup work'
110
+    assert did_cleanup is None or bool(did_cleanup) == (obj != obj_), (
111
+        'mismatched report on cleanup work'
112
+    )
113 113
 
114 114
 
115 115
 @pytest.mark.parametrize(
... ...
@@ -147,9 +147,9 @@ def test_400_validate_vault_config(test_config: tests.VaultTestConfig) -> None:
147 147
 def test_400a_validate_vault_config_smudged(
148 148
     test_config: tests.VaultTestConfig,
149 149
 ) -> None:
150
-    _obj, comment, validation_settings = test_config
150
+    obj_, comment, validation_settings = test_config
151 151
     (allow_unknown_settings,) = validation_settings or (True,)
152
-    obj = copy.deepcopy(_obj)
152
+    obj = copy.deepcopy(obj_)
153 153
     did_cleanup = _types.clean_up_falsy_vault_config_values(obj)
154 154
     if comment:
155 155
         with pytest.raises((TypeError, ValueError)):
... ...
@@ -165,6 +165,6 @@ def test_400a_validate_vault_config_smudged(
165 165
             )
166 166
         except (TypeError, ValueError) as exc:  # pragma: no cover
167 167
             assert not exc, 'failed to validate valid example'  # noqa: PT017
168
-    assert did_cleanup is None or bool(did_cleanup) == (
169
-        obj != _obj
170
-    ), 'mismatched report on cleanup work'
168
+    assert did_cleanup is None or bool(did_cleanup) == (obj != obj_), (
169
+        'mismatched report on cleanup work'
170
+    )
... ...
@@ -350,9 +350,9 @@ class TestHypotheses:
350 350
                 # appear via the other character class.
351 351
                 assert True
352 352
             else:
353
-                assert (
354
-                    sum(c in Vault._CHARSETS[key] for c in password) == 0
355
-                ), 'Password does not satisfy character ban constraints.'
353
+                assert sum(c in Vault._CHARSETS[key] for c in password) == 0, (
354
+                    'Password does not satisfy character ban constraints.'
355
+                )
356 356
 
357 357
         T = TypeVar('T', str, bytes)
358 358
 
... ...
@@ -363,9 +363,9 @@ class TestHypotheses:
363 363
         repeat = config['repeat']
364 364
         if repeat:
365 365
             for snippet in length_r_substrings(password, r=(repeat + 1)):
366
-                assert (
367
-                    len(set(snippet)) > 1
368
-                ), 'Password does not satisfy character repeat constraints.'
366
+                assert len(set(snippet)) > 1, (
367
+                    'Password does not satisfy character repeat constraints.'
368
+                )
369 369
 
370 370
     @tests.hypothesis_settings_coverage_compatible
371 371
     @hypothesis.given(
372 372