Convert informal upgrade comments to proper TODOs
Marco Ricci

Marco Ricci commited on 2025-01-23 10:53:54
Zeige 7 geänderte Dateien mit 56 Einfügungen und 19 Löschungen.


This includes a short instruction and a link to the upgrade notes or
Python compatibility section related to this code section.
... ...
@@ -291,7 +291,9 @@ class _VaultConfigValidator:
291 291
             kwargs['key'] = key
292 292
             kwargs['value'] = value
293 293
             kwargs['json_path_str'] = json_path([*path, key])
294
-            # Use match/case here once Python 3.9 becomes unsupported.
294
+            # TODO(the-13th-letter): Rewrite using structural pattern
295
+            # matching.
296
+            # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
295 297
             if key in {'key', 'phrase'}:
296 298
                 if not isinstance(value, str):
297 299
                     raise TypeError(err_not_a_string.format(**kwargs))
... ...
@@ -353,7 +355,9 @@ class _VaultConfigValidator:
353 355
 
354 356
         for path, key, value in self.walk_subconfigs():
355 357
             service_obj = self.traverse_path(path)
356
-            # Use match/case here once Python 3.9 becomes unsupported.
358
+            # TODO(the-13th-letter): Rewrite using structural pattern
359
+            # matching.
360
+            # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
357 361
             if key == 'phrase' and falsy_but_not_string(value):
358 362
                 yield CleanupStep(
359 363
                     (*path, key), service_obj[key], 'replace', ''
... ...
@@ -454,6 +458,8 @@ def validate_vault_config(
454 458
             specified `derivepassphrase` extensions.
455 459
 
456 460
     """
461
+    # TODO(the-13th-letter): Remove this block in v1.0.
462
+    # https://the13thletter.info/derivepassphrase/latest/upgrade-notes/#v1.0-allow-derivepassphrase-extensions
457 463
     # TODO(the-13th-letter): Add tests that trigger the deprecation warning,
458 464
     # then include this in coverage.
459 465
     if not isinstance(
... ...
@@ -593,6 +599,8 @@ def clean_up_falsy_vault_config_values(
593 599
         return None
594 600
 
595 601
 
602
+# TODO(the-13th-letter): Use type variables local to each class.
603
+# https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.11
596 604
 T_Buffer = TypeVar('T_Buffer', bound=Buffer)
597 605
 """
598 606
 A [`TypeVar`][] for classes implementing the [`Buffer`][] interface.
... ...
@@ -1111,6 +1111,9 @@ if (
1111 1111
 #     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
1112 1112
 #     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1113 1113
 #     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1114
+#
1115
+# TODO(the-13th-letter): Remove this class and license block in v1.0.
1116
+# https://the13thletter.info/derivepassphrase/latest/upgrade-notes/#v1.0-implied-subcommands
1114 1117
 class _DefaultToVaultGroup(CommandWithHelpGroups, click.Group):
1115 1118
     """A helper class to implement the default-to-"vault"-subcommand behavior.
1116 1119
 
... ...
@@ -1166,6 +1169,9 @@ class _DefaultToVaultGroup(CommandWithHelpGroups, click.Group):
1166 1169
         return cmd_name if cmd else None, cmd, args[1:]
1167 1170
 
1168 1171
 
1172
+# TODO(the-13th-letter): Base this class on CommandWithHelpGroups and
1173
+# click.Group in v1.0.
1174
+# https://the13thletter.info/derivepassphrase/latest/upgrade-notes/#v1.0-implied-subcommands
1169 1175
 class _TopLevelCLIEntryPoint(_DefaultToVaultGroup):
1170 1176
     """A minor variation of _DefaultToVaultGroup for the top-level command.
1171 1177
 
... ...
@@ -1227,6 +1233,8 @@ def derivepassphrase(ctx: click.Context, /) -> None:
1227 1233
     [CLICK]: https://pypi.org/package/click/
1228 1234
 
1229 1235
     """
1236
+    # TODO(the-13th-letter): Turn this callback into a no-op in v1.0.
1237
+    # https://the13thletter.info/derivepassphrase/latest/upgrade-notes/#v1.0-implied-subcommands
1230 1238
     deprecation = logging.getLogger(f'{PROG_NAME}.deprecation')
1231 1239
     if ctx.invoked_subcommand is None:
1232 1240
         deprecation.warning(
... ...
@@ -1280,6 +1288,8 @@ def derivepassphrase_export(ctx: click.Context, /) -> None:
1280 1288
     [CLICK]: https://pypi.org/package/click/
1281 1289
 
1282 1290
     """
1291
+    # TODO(the-13th-letter): Turn this callback into a no-op in v1.0.
1292
+    # https://the13thletter.info/derivepassphrase/latest/upgrade-notes/#v1.0-implied-subcommands
1283 1293
     deprecation = logging.getLogger(f'{PROG_NAME}.deprecation')
1284 1294
     if ctx.invoked_subcommand is None:
1285 1295
         deprecation.warning(
... ...
@@ -1465,6 +1475,8 @@ _config_filename_table = {
1465 1475
     None: '.',
1466 1476
     'vault': 'vault.json',
1467 1477
     'user configuration': 'config.toml',
1478
+    # TODO(the-13th-letter): Remove the old settings.json file.
1479
+    # https://the13thletter.info/derivepassphrase/latest/upgrade-notes.html#v1.0-old-settings-file
1468 1480
     'old settings.json': 'settings.json',
1469 1481
 }
1470 1482
 
... ...
@@ -1535,6 +1547,8 @@ def _load_config() -> _types.VaultConfig:
1535 1547
     return data
1536 1548
 
1537 1549
 
1550
+# TODO(the-13th-letter): Remove this function.
1551
+# https://the13thletter.info/derivepassphrase/latest/upgrade-notes.html#v1.0-old-settings-file
1538 1552
 def _migrate_and_load_old_config() -> tuple[
1539 1553
     _types.VaultConfig, OSError | None
1540 1554
 ]:
... ...
@@ -44,7 +44,8 @@ class SSHAgentFailedError(RuntimeError):
44 44
     """The SSH agent failed to complete the requested operation."""
45 45
 
46 46
     def __str__(self) -> str:
47
-        # Use match/case here once Python 3.9 becomes unsupported.
47
+        # TODO(the-13th-letter): Rewrite using structural pattern matching.
48
+        # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
48 49
         if self.args == (  # pragma: no branch
49 50
             _types.SSH_AGENT.FAILURE.value,
50 51
             b'',
... ...
@@ -327,7 +328,8 @@ class SSHAgentClient:
327 328
                 setting up a socket connection to the agent.
328 329
 
329 330
         """  # noqa: DOC501
330
-        # Use match/case here once Python 3.9 becomes unsupported.
331
+        # TODO(the-13th-letter): Rewrite using structural pattern matching.
332
+        # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
331 333
         if isinstance(conn, SSHAgentClient):
332 334
             with contextlib.nullcontext():
333 335
                 yield conn
... ...
@@ -1433,8 +1433,8 @@ def isolated_config(
1433 1433
 ) -> Iterator[None]:
1434 1434
     prog_name = cli.PROG_NAME
1435 1435
     env_name = prog_name.replace(' ', '_').upper() + '_PATH'
1436
-    # Use parenthesized context manager expressions once Python 3.9
1437
-    # becomes unsupported.
1436
+    # TODO(the-13th-letter): Rewrite using parenthesized with-statements.
1437
+    # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
1438 1438
     with contextlib.ExitStack() as stack:
1439 1439
         stack.enter_context(runner.isolated_filesystem())
1440 1440
         stack.enter_context(cli.StandardCLILogging.ensure_standard_logging())
... ...
@@ -1477,6 +1477,8 @@ def isolated_vault_exporter_config(
1477 1477
     vault_config: str | bytes | None = None,
1478 1478
     vault_key: str | None = None,
1479 1479
 ) -> Iterator[None]:
1480
+    # TODO(the-13th-letter): Remove the fallback implementation.
1481
+    # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.10
1480 1482
     if TYPE_CHECKING:
1481 1483
         chdir: Callable[..., AbstractContextManager]
1482 1484
     else:
... ...
@@ -1505,13 +1507,15 @@ def isolated_vault_exporter_config(
1505 1507
         if vault_key is not None:
1506 1508
             monkeypatch.setenv('VAULT_KEY', vault_key)
1507 1509
         vault_config_path = pathlib.Path('.vault').resolve()
1508
-        # Use match/case here once Python 3.9 becomes unsupported.
1510
+        # TODO(the-13th-letter): Rewrite using structural pattern matching.
1511
+        # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
1509 1512
         if isinstance(vault_config, str):
1510 1513
             vault_config_path.write_text(f'{vault_config}\n', encoding='UTF-8')
1511 1514
         elif isinstance(vault_config, bytes):
1512 1515
             vault_config_path.mkdir(parents=True, mode=0o700, exist_ok=True)
1513
-            # Use parenthesized context manager expressions here once
1514
-            # Python 3.9 becomes unsupported.
1516
+            # TODO(the-13th-letter): Rewrite using parenthesized
1517
+            # with-statements.
1518
+            # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
1515 1519
             with contextlib.ExitStack() as stack:
1516 1520
                 stack.enter_context(chdir(vault_config_path))
1517 1521
                 tmpzipfile = stack.enter_context(
... ...
@@ -1647,7 +1651,8 @@ class ReadableResult(NamedTuple):
1647 1651
                 else error.match(line) is not None
1648 1652
             )
1649 1653
 
1650
-        # Use match/case here once Python 3.9 becomes unsupported.
1654
+        # TODO(the-13th-letter): Rewrite using structural pattern matching.
1655
+        # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
1651 1656
         if isinstance(error, type):
1652 1657
             return isinstance(self.exception, error)
1653 1658
         else:  # noqa: RET505
... ...
@@ -2086,8 +2086,9 @@ class TestCLIUtils:
2086 2086
         self, monkeypatch: pytest.MonkeyPatch
2087 2087
     ) -> None:
2088 2088
         runner = click.testing.CliRunner()
2089
-        # Use parenthesized context manager expressions here once Python
2090
-        # 3.9 becomes unsupported.
2089
+        # TODO(the-13th-letter): Rewrite using parenthesized
2090
+        # with-statements.
2091
+        # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
2091 2092
         with contextlib.ExitStack() as stack:
2092 2093
             stack.enter_context(
2093 2094
                 tests.isolated_vault_config(
... ...
@@ -2632,7 +2633,9 @@ Boo.
2632 2633
                 ssh_agent.SSHAgentClient, 'list_keys', tests.list_keys
2633 2634
             )
2634 2635
             hint: ssh_agent.SSHAgentClient | socket.socket | None
2635
-            # Use match/case here once Python 3.9 becomes unsupported.
2636
+            # TODO(the-13th-letter): Rewrite using structural pattern
2637
+            # matching.
2638
+            # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
2636 2639
             if conn_hint == 'client':
2637 2640
                 hint = ssh_agent.SSHAgentClient()
2638 2641
             elif conn_hint == 'socket':
... ...
@@ -2737,6 +2740,8 @@ Boo.
2737 2740
                 cli._key_to_phrase(loaded_key, error_callback=err)
2738 2741
 
2739 2742
 
2743
+# TODO(the-13th-letter): Remove this class in v1.0.
2744
+# https://the13thletter.info/derivepassphrase/latest/upgrade-notes/#upgrading-to-v1.0
2740 2745
 class TestCLITransition:
2741 2746
     def test_100_help_output(self, monkeypatch: pytest.MonkeyPatch) -> None:
2742 2747
         runner = click.testing.CliRunner(mix_stderr=False)
... ...
@@ -404,8 +404,9 @@ class TestStoreroom:
404 404
         handler: exporter.ExportVaultConfigDataFunction,
405 405
     ) -> None:
406 406
         runner = click.testing.CliRunner(mix_stderr=False)
407
-        # Use parenthesized context manager expressions once Python 3.9
408
-        # becomes unsupported.
407
+        # TODO(the-13th-letter): Rewrite using parenthesized
408
+        # with-statements.
409
+        # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
409 410
         with contextlib.ExitStack() as stack:
410 411
             stack.enter_context(
411 412
                 tests.isolated_vault_exporter_config(
... ...
@@ -590,8 +590,9 @@ class TestAgentInteraction:
590 590
     ) -> None:
591 591
         del running_ssh_agent
592 592
 
593
-        # Use parenthesized context manager expressions once Python 3.9
594
-        # becomes unsupported.
593
+        # TODO(the-13th-letter): Rewrite using parenthesized
594
+        # with-statements.
595
+        # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
595 596
         with contextlib.ExitStack() as stack:
596 597
             stack.enter_context(pytest.raises(exc_type, match=exc_pattern))
597 598
             client = stack.enter_context(ssh_agent.SSHAgentClient())
... ...
@@ -652,8 +653,9 @@ class TestAgentInteraction:
652 653
                 assert single_code in response_codes
653 654
             return response_data  # pragma: no cover
654 655
 
655
-        # Use parenthesized context manager expressions once Python 3.9
656
-        # becomes unsupported.
656
+        # TODO(the-13th-letter): Rewrite using parenthesized
657
+        # with-statements.
658
+        # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
657 659
         with contextlib.ExitStack() as stack:
658 660
             monkeypatch2 = stack.enter_context(monkeypatch.context())
659 661
             client = stack.enter_context(ssh_agent.SSHAgentClient())
660 662