Marco Ricci commited on 2025-02-15 00:01:29
Zeige 3 geänderte Dateien mit 57 Einfügungen und 1 Löschungen.
Emit known and supported features in the version output, such as master SSH key support for the `vault` subcommand.
... | ... |
@@ -20,6 +20,7 @@ import importlib.metadata |
20 | 20 |
import inspect |
21 | 21 |
import logging |
22 | 22 |
import os |
23 |
+import socket |
|
23 | 24 |
import warnings |
24 | 25 |
from typing import TYPE_CHECKING, Callable, Literal, TextIO, TypeVar |
25 | 26 |
|
... | ... |
@@ -1126,6 +1127,19 @@ def vault_version_option_callback( |
1126 | 1127 |
) -> None: |
1127 | 1128 |
if value and not ctx.resilient_parsing: |
1128 | 1129 |
common_version_output(ctx, param, value) |
1130 |
+ features = { |
|
1131 |
+ 'master SSH key': hasattr(socket, 'AF_UNIX'), |
|
1132 |
+ } |
|
1133 |
+ click.echo() |
|
1134 |
+ version_info_types = { |
|
1135 |
+ _msg.Label.SUPPORTED_FEATURES: [ |
|
1136 |
+ k for k, v in features.items() if v |
|
1137 |
+ ], |
|
1138 |
+ _msg.Label.KNOWN_FEATURES: [ |
|
1139 |
+ k for k, v in features.items() if not v |
|
1140 |
+ ], |
|
1141 |
+ } |
|
1142 |
+ print_version_info_types(version_info_types, ctx=ctx) |
|
1129 | 1143 |
ctx.exit() |
1130 | 1144 |
|
1131 | 1145 |
|
... | ... |
@@ -1300,6 +1300,16 @@ class Label(enum.Enum): |
1300 | 1300 |
'Known derivation schemes:', |
1301 | 1301 |
) |
1302 | 1302 |
"""""" |
1303 |
+ KNOWN_FEATURES = commented( |
|
1304 |
+ 'This is part of the version output, emitting lists of known, ' |
|
1305 |
+ 'unavailable features for this subcommand. ' |
|
1306 |
+ 'A comma-separated English list of items follows, ' |
|
1307 |
+ 'with standard English punctuation.', |
|
1308 |
+ )( |
|
1309 |
+ 'Label :: Info Message:: Table row header', |
|
1310 |
+ 'Known features:', |
|
1311 |
+ ) |
|
1312 |
+ """""" |
|
1303 | 1313 |
KNOWN_FOREIGN_CONFIGURATION_FORMATS = commented( |
1304 | 1314 |
'This is part of the version output, emitting lists of known ' |
1305 | 1315 |
'foreign configuration formats. A comma-separated English list ' |
... | ... |
@@ -1318,6 +1328,15 @@ class Label(enum.Enum): |
1318 | 1328 |
'Supported derivation schemes:', |
1319 | 1329 |
) |
1320 | 1330 |
"""""" |
1331 |
+ SUPPORTED_FEATURES = commented( |
|
1332 |
+ 'This is part of the version output, emitting lists of supported ' |
|
1333 |
+ 'features for this subcommand. A comma-separated ' |
|
1334 |
+ 'English list of items follows, with standard English punctuation.', |
|
1335 |
+ )( |
|
1336 |
+ 'Label :: Info Message:: Table row header', |
|
1337 |
+ 'Supported features:', |
|
1338 |
+ ) |
|
1339 |
+ """""" |
|
1321 | 1340 |
SUPPORTED_FOREIGN_CONFIGURATION_FORMATS = commented( |
1322 | 1341 |
'This is part of the version output, emitting lists of supported ' |
1323 | 1342 |
'foreign configuration formats. A comma-separated English list ' |
... | ... |
@@ -86,6 +86,7 @@ class VersionOutputData(NamedTuple): |
86 | 86 |
foreign_configuration_formats: dict[str, bool] |
87 | 87 |
extras: frozenset[str] |
88 | 88 |
subcommands: frozenset[str] |
89 |
+ features: dict[str, bool] |
|
89 | 90 |
|
90 | 91 |
|
91 | 92 |
PASSPHRASE_GENERATION_OPTIONS: list[tuple[str, ...]] = [ |
... | ... |
@@ -405,12 +406,14 @@ def parse_version_output( # noqa: C901 |
405 | 406 |
formats: dict[str, bool] = {} |
406 | 407 |
subcommands: set[str] = set() |
407 | 408 |
extras: set[str] = set() |
408 |
- if len(paragraphs) < 2: |
|
409 |
+ features: dict[str, bool] = {} |
|
410 |
+ if len(paragraphs) < 2: # pragma: no cover |
|
409 | 411 |
return VersionOutputData( |
410 | 412 |
derivation_schemes=schemes, |
411 | 413 |
foreign_configuration_formats=formats, |
412 | 414 |
subcommands=frozenset(subcommands), |
413 | 415 |
extras=frozenset(extras), |
416 |
+ features=features, |
|
414 | 417 |
) |
415 | 418 |
for line in paragraphs[1]: |
416 | 419 |
line_type, _, value = line.partition(':') |
... | ... |
@@ -432,6 +435,10 @@ def parse_version_output( # noqa: C901 |
432 | 435 |
subcommands.add(item) |
433 | 436 |
elif line_type == 'PEP 508 extras': |
434 | 437 |
extras.add(item) |
438 |
+ elif line_type == 'Supported features': |
|
439 |
+ features[item] = True |
|
440 |
+ elif line_type == 'Known features': |
|
441 |
+ features[item] = False |
|
435 | 442 |
else: |
436 | 443 |
raise AssertionError( # noqa: TRY003 |
437 | 444 |
f'Unknown version info line type: {line_type!r}' # noqa: EM102 |
... | ... |
@@ -441,6 +448,7 @@ def parse_version_output( # noqa: C901 |
441 | 448 |
foreign_configuration_formats=formats, |
442 | 449 |
subcommands=frozenset(subcommands), |
443 | 450 |
extras=frozenset(extras), |
451 |
+ features=features, |
|
444 | 452 |
) |
445 | 453 |
|
446 | 454 |
|
... | ... |
@@ -1481,6 +1489,7 @@ PEP 508 extras: export. |
1481 | 1489 |
'vault v0.3': True, |
1482 | 1490 |
}, |
1483 | 1491 |
subcommands=frozenset(), |
1492 |
+ features={}, |
|
1484 | 1493 |
extras=frozenset({'export'}), |
1485 | 1494 |
), |
1486 | 1495 |
id='derivepassphrase-0.4.0-export', |
... | ... |
@@ -1504,6 +1513,7 @@ No PEP 508 extras are active. |
1504 | 1513 |
'vault v0.3': False, |
1505 | 1514 |
}, |
1506 | 1515 |
subcommands=frozenset({'export', 'vault'}), |
1516 |
+ features={}, |
|
1507 | 1517 |
extras=frozenset({}), |
1508 | 1518 |
), |
1509 | 1519 |
id='derivepassphrase-0.5-plain', |
... | ... |
@@ -1525,6 +1535,8 @@ Supported foreign configuration formats: derivepassphrase, nonsense. |
1525 | 1535 |
Known foreign configuration formats: divination v3.141592, |
1526 | 1536 |
/dev/random. |
1527 | 1537 |
Supported subcommands: delete-all-files, dump-core. |
1538 |
+Supported features: delete-while-open. |
|
1539 |
+Known features: backups-are-nice-to-have. |
|
1528 | 1540 |
PEP 508 extras: annoying-popups, delete-all-files, |
1529 | 1541 |
dump-core-depending-on-the-phase-of-the-moon. |
1530 | 1542 |
|
... | ... |
@@ -1548,6 +1560,10 @@ PEP 508 extras: annoying-popups, delete-all-files, |
1548 | 1560 |
'/dev/random': False, |
1549 | 1561 |
}, |
1550 | 1562 |
subcommands=frozenset({'delete-all-files', 'dump-core'}), |
1563 |
+ features={ |
|
1564 |
+ 'delete-while-open': True, |
|
1565 |
+ 'backups-are-nice-to-have': False, |
|
1566 |
+ }, |
|
1551 | 1567 |
extras=frozenset({ |
1552 | 1568 |
'annoying-popups', |
1553 | 1569 |
'delete-all-files', |
... | ... |
@@ -1837,6 +1853,7 @@ class TestAllCLI: |
1837 | 1853 |
assert version_data.derivation_schemes == actually_known_schemes |
1838 | 1854 |
assert not version_data.foreign_configuration_formats |
1839 | 1855 |
assert version_data.subcommands == subcommands |
1856 |
+ assert not version_data.features |
|
1840 | 1857 |
assert not version_data.extras |
1841 | 1858 |
|
1842 | 1859 |
def test_202b_export_version_option_output( |
... | ... |
@@ -1885,6 +1902,7 @@ class TestAllCLI: |
1885 | 1902 |
== actually_known_formats |
1886 | 1903 |
) |
1887 | 1904 |
assert version_data.subcommands == subcommands |
1905 |
+ assert not version_data.features |
|
1888 | 1906 |
assert not version_data.extras |
1889 | 1907 |
|
1890 | 1908 |
def test_202c_export_vault_version_option_output( |
... | ... |
@@ -1939,6 +1957,7 @@ class TestAllCLI: |
1939 | 1957 |
== actually_known_formats |
1940 | 1958 |
) |
1941 | 1959 |
assert not version_data.subcommands |
1960 |
+ assert not version_data.features |
|
1942 | 1961 |
assert version_data.extras == actually_enabled_extras |
1943 | 1962 |
|
1944 | 1963 |
def test_202d_vault_version_option_output( |
... | ... |
@@ -1974,9 +1993,13 @@ class TestAllCLI: |
1974 | 1993 |
assert result.clean_exit(empty_stderr=True), 'expected clean exit' |
1975 | 1994 |
assert result.output.strip(), 'expected version output' |
1976 | 1995 |
version_data = parse_version_output(result.output) |
1996 |
+ features: dict[str, bool] = { |
|
1997 |
+ 'master SSH key': hasattr(socket, 'AF_UNIX'), |
|
1998 |
+ } |
|
1977 | 1999 |
assert not version_data.derivation_schemes |
1978 | 2000 |
assert not version_data.foreign_configuration_formats |
1979 | 2001 |
assert not version_data.subcommands |
2002 |
+ assert version_data.features == features |
|
1980 | 2003 |
assert not version_data.extras |
1981 | 2004 |
|
1982 | 2005 |
|
1983 | 2006 |