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 |