Recent commits to derivepassphrase.git (59d73c8320650a6bcb77eed759c694949d350cdb) https://git.schokokeks.org/derivepassphrase.git/tree/59d73c8320650a6bcb77eed759c694949d350cdb Recent commits feed provided by GitList. Update the CLI to use the translatable strings We implement the translations in a deferred manner, via objects that stringify to their correct translation. Since `click` 8.1, help texts are (mostly) stored first and processed only when the help page is emitted. Accordingly, this system can be adapted to support our translatable strings: we need only ensure the help text is stringified just before it is formatted and emitted. This in turn can be achieved by reimplementing the help page assembly and formatting in a custom `click.Command` class, as has already been done to implement help/option group support. Once this is in place, it remains to exchange all inline help texts with the corresponding translatable string, and adapt the tests to the new messages. While most of the changes are straightforward, some subtleties remain. First, the help texts are now supplied as (separately translatable) paragraphs to the `click.command` decorator, instead of being extracted from the respective function docstring. The docstrings in return have been shortened down. Second, since the new capabilities are implemented via custom `click.Command`, `click.MultiCommand` and `click.Option` subclasses, every option and command must derive from one of these classes. This necessitates the creation of an empty `StandardOption` class for options without an option group, and making `_DefaultToVaultGroup` a subclass of `CommandWithHelpGroups`. Third, since the `click.Option` class actually processes its help text eagerly, the subclass must hide the (non-string) help text from the `click.Option` constructor and later restore it. Finally, while the tests currently pass as before, they now implicitly rely on *not* loading any translations. Furthermore, there is no mechanism in place with which to isolate the translation system from the user's environment for testing purposes, nor is there a (controlled) mechanism to test `derivepassphrase` under a different language. Once there are actual translations, future commits will need to establish such a missing mechanism for translation loading/switching/forcing. https://git.schokokeks.org/derivepassphrase.git/commit/59d73c8320650a6bcb77eed759c694949d350cdb software@the13thletter.info (Marco Ricci) Mon, 30 Dec 2024 23:45:01 +0100 59d73c8320650a6bcb77eed759c694949d350cdb Add more translatable strings and serialization machinery Add all help texts and metavars as translatable strings. Furthermore, add extra machinery for introspection to the serialized translatable strings class, which will make debugging values in pytest much easier. Add another couple of error messages (and update the manpages as well) for low-level errors while querying the SSH agent for the key list or while requesting a signature. (Previously, we forwarded the internal English exception message directly.) Update the manpage to include these as well. https://git.schokokeks.org/derivepassphrase.git/commit/df1756fe1222e9bf01b9f256a8a212174c144876 software@the13thletter.info (Marco Ricci) Mon, 30 Dec 2024 21:34:42 +0100 df1756fe1222e9bf01b9f256a8a212174c144876 Extract translatable log messages into separate module Extract all log messages into a separate module, so that they may be translated in a future version. We anticipate the use of such a message in a `logging` call, so we provide a wrapper object that defers the string interpolation until its serialization is called, and caches the result. (This is all as per the recommendation from the standard `logging` module.) Implemented this way, it is easy to run easy transformations on the specific log message template, e.g. substituting a translated message template, or trimming the filename placeholder if the filename is `None`. As an added benefit, this organization also makes it somewhat easy to ensure message consistency across different use sites and to generate diagnostics lists for inclusion in the manpage. While we intend to use the gettext toolset to implement the translation later, we do *not* currently use the standard `_` gettext alias or otherwise mark up the strings in an `xgettext`-compatible manner. Both the GNU version of `xgettext` and the Python work-alike `xgettext.py` suck: the GNU version does not completely understand Python syntax and cannot sensibly parse `black`-/`ruff`-formatted code using implicit string concatenation or trailing commas in function argument lists, and `xgettext.py` is so outdated (even in current Pythons) that it does not support `xgettext`'s `--add-comment` option for extracting extra comments for the translators. So instead of attempting to cram the strings and comments into some formatter-resistant and `xgettext`-compatible shape (a very futile endeavor so far), store enough information that we could generate the `.po` files ourselves with very little additional effort. https://git.schokokeks.org/derivepassphrase.git/commit/317489552ba4585e773775417b4d3f106538f98b software@the13thletter.info (Marco Ricci) Wed, 25 Dec 2024 21:41:22 +0100 317489552ba4585e773775417b4d3f106538f98b Add an actual derivepassphrase-vault(1) manpage, plus better manpage contents The barebones HTML "manpage" for `derivepassphrase` was essentially an HTML-ized version of the help text. In particular, the option descriptions only contained the one-line help text, and many typical sections (FILES, ENVIRONMENT, EXAMPLES, DIAGNOSTICS, AUTHOR, BUGS) were missing. This commit contributes a proper manpage, in `*roff`/`mdoc` format. It was authored using guidance from the `groff_mdoc` documentation, the only sensible-appearing authoritative source on manpage style issues. (Perl's `perlpodstyle`, `groff_man` and `groff_man_style` were also consulted, but ultimately disregarded.) The content changes were also folded back into the HTML version, save for some styling choices that aren't possible in the `*roff` version. In particular, both versions are hand-written, and manually synchronized with each other. The manpages use the option group headings "Passphrase generation" and "Compatibility and extension options" instead of "Password generation" and "Options concerning compatibility with other tools", for better text flow. Accordingly, this phrasing has been adapted in `derivepassphrase_vault` as well. https://git.schokokeks.org/derivepassphrase.git/commit/8154b0ff2bedbc2a7ec7d812091067084555aa31 software@the13thletter.info (Marco Ricci) Wed, 25 Dec 2024 20:55:45 +0100 8154b0ff2bedbc2a7ec7d812091067084555aa31 Make the mutually exclusive options helper function print the correct parameter name The `click.Parameter.human_readable_name` attribute yields the metavar for arguments, and the function parameter name for options. The documentation calls the latter the "name" for the option, perhaps under the assumption that you would never pass an explicit parameter name to the option decorator. I disagree with this, it is horrible design: sometimes the value is usable as a function parameter (options), sometimes it isn't (arguments), and vice versa for constructing a command-line, so it is neither usable as a command-line parameter display name nor as a function parameter name. So what *is* it even good for...? Include our own logic to select an appropriate display name for our options. This requires querying `click.Parameter` attributes that should be public, but are internal. Why...?! https://git.schokokeks.org/derivepassphrase.git/commit/208429075c67c884f55d76474e8c8a4baea616ab software@the13thletter.info (Marco Ricci) Wed, 25 Dec 2024 18:59:32 +0100 208429075c67c884f55d76474e8c8a4baea616ab Add small fixes to changelog, docstrings and variable names https://git.schokokeks.org/derivepassphrase.git/commit/4bfbfa3c9eb2e4a82707289da46fa3665aa24283 software@the13thletter.info (Marco Ricci) Wed, 25 Dec 2024 17:15:23 +0100 4bfbfa3c9eb2e4a82707289da46fa3665aa24283 Instruct `coverage` to record the test function for each covered line Enable the standard dynamic context setting `test_function` for `coverage`. This is immensely helpful for debugging whether and which tests trigger or don't trigger a certain branch of code in a multi-branch block (`if`/`elif`/`else`, `match`/`case` blocks, dispatch tables, etc.). https://git.schokokeks.org/derivepassphrase.git/commit/bdf02f629dc0dbc1b72d74f56a6edb06d681ab60 software@the13thletter.info (Marco Ricci) Sat, 21 Dec 2024 01:02:34 +0100 bdf02f629dc0dbc1b72d74f56a6edb06d681ab60 Fix formatting, some coverage pragmas and some linting rules in tests Aside from formatting fixes, disable the E501/line-too-long and C419/unnecessary-comprehension-in-call linting rules in tests, where they hinder debuggability of the tests. (See embedded comments for full rationale.) Furthermore, make `coverage` recognize `@overload` lines automatically as lines that should not be included in coverage, like `assert False` and friends. https://git.schokokeks.org/derivepassphrase.git/commit/f36630533e3f8d9932e4b1b2975ec3d8bde7b45a software@the13thletter.info (Marco Ricci) Sat, 21 Dec 2024 00:57:49 +0100 f36630533e3f8d9932e4b1b2975ec3d8bde7b45a Support exporting the `vault` configuration as a POSIX shell script When exporting `vault` configurations via `--export`, a new option `--export-as=FORMAT` allows selecting the export format (defaulting to `json`). Setting `FORMAT` as `sh` selects the new POSIX shell script export format, which yields a sh(1)-compatible script to reimport the existing configuration as a series of calls to the `derivepassphrase` command. Because the output is very regular, the test suite also includes an interpreter specifically for the sh(1) subset emitted during an `sh` export, on top of the usual adaptations to existing tests for the new functionality. https://git.schokokeks.org/derivepassphrase.git/commit/cefe3175dd103226d6d404886a091f6dfe85026f software@the13thletter.info (Marco Ricci) Sat, 21 Dec 2024 00:23:33 +0100 cefe3175dd103226d6d404886a091f6dfe85026f Allow unsetting settings when configuring `vault` When configuring a `vault` service, or the global settings, a new configuration option `--unset FIELD` will unset the specified `FIELD` from the service or global settings prior to and addition to applying the requested settings changes. This way, the user can update all settings on the command-line (except for the "notes") without manually editing and reimporting a configuration export. (It is permissible to only unset settings, without applying any other configuration changes.) https://git.schokokeks.org/derivepassphrase.git/commit/7a43a0cf4ea5877b3ff07576d5ee5c3ad36c087b software@the13thletter.info (Marco Ricci) Fri, 20 Dec 2024 17:00:48 +0100 7a43a0cf4ea5877b3ff07576d5ee5c3ad36c087b