8f9fa0e9819f814b7638a3dd8f705ac6b84d2611
Marco Ricci Change the author e-mail ad...

Marco Ricci authored 4 months ago

1) # SPDX-FileCopyrightText: 2024 Marco Ricci <software@the13thletter.info>
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2) #
3) # SPDX-License-Identifier: MIT
4) 
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

5) # ruff: noqa: TRY400
6) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

7) """Command-line interface for derivepassphrase."""
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

8) 
9) from __future__ import annotations
10) 
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

11) import base64
12) import collections
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

13) import copy
Marco Ricci Signal and list falsy value...

Marco Ricci authored 3 months ago

14) import enum
Marco Ricci Rewrite incompatible option...

Marco Ricci authored 3 weeks ago

15) import functools
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

16) import importlib
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

17) import inspect
18) import json
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

19) import logging
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

20) import os
Marco Ricci Support exporting the `vaul...

Marco Ricci authored 2 weeks ago

21) import shlex
Marco Ricci Introduce a central user co...

Marco Ricci authored 3 weeks ago

22) import sys
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

23) import unicodedata
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

24) import warnings
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

25) from typing import (
26)     TYPE_CHECKING,
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

27)     Callable,
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

28)     Literal,
Marco Ricci Use better error message ha...

Marco Ricci authored 4 months ago

29)     NoReturn,
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

30)     TextIO,
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

31)     TypeVar,
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

32)     cast,
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

33) )
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

34) 
35) import click
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

36) from typing_extensions import (
37)     Any,
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

38)     ParamSpec,
39)     Self,
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

40)     assert_never,
41) )
42) 
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

43) import derivepassphrase as dpp
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

44) from derivepassphrase import _cli_msg as _msg
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

45) from derivepassphrase import _types, exporter, ssh_agent, vault
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

46) 
Marco Ricci Introduce a central user co...

Marco Ricci authored 3 weeks ago

47) if sys.version_info >= (3, 11):
48)     import tomllib
49) else:
50)     import tomli as tomllib
51) 
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

52) if TYPE_CHECKING:
53)     import pathlib
Marco Ricci Support one-off SSH agent c...

Marco Ricci authored 1 month ago

54)     import socket
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

55)     import types
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

56)     from collections.abc import (
57)         Iterator,
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

58)         MutableSequence,
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

59)         Sequence,
60)     )
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

61) 
62) __author__ = dpp.__author__
63) __version__ = dpp.__version__
64) 
65) __all__ = ('derivepassphrase',)
66) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

67) PROG_NAME = _msg.PROG_NAME
Marco Ricci Make suitable SSH key listi...

Marco Ricci authored 1 month ago

68) KEY_DISPLAY_LENGTH = 50
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

69) 
70) # Error messages
71) _INVALID_VAULT_CONFIG = 'Invalid vault config'
72) _AGENT_COMMUNICATION_ERROR = 'Error communicating with the SSH agent'
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

73) _NO_SUITABLE_KEYS = 'No suitable SSH keys were found'
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

74) _EMPTY_SELECTION = 'Empty selection'
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

75) _NOT_AN_INTEGER = 'not an integer'
76) _NOT_A_NONNEGATIVE_INTEGER = 'not a non-negative integer'
77) _NOT_A_POSITIVE_INTEGER = 'not a positive integer'
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

78) 
79) 
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

80) # Logging
81) # =======
82) 
83) 
84) class ClickEchoStderrHandler(logging.Handler):
85)     """A [`logging.Handler`][] for `click` applications.
86) 
87)     Outputs log messages to [`sys.stderr`][] via [`click.echo`][].
88) 
89)     """
90) 
91)     def emit(self, record: logging.LogRecord) -> None:
92)         """Emit a log record.
93) 
94)         Format the log record, then emit it via [`click.echo`][] to
95)         [`sys.stderr`][].
96) 
97)         """
98)         click.echo(self.format(record), err=True)
99) 
100) 
101) class CLIofPackageFormatter(logging.Formatter):
102)     """A [`logging.LogRecord`][] formatter for the CLI of a Python package.
103) 
104)     Assuming a package `PKG` and loggers within the same hierarchy
105)     `PKG`, format all log records from that hierarchy for proper user
106)     feedback on the console.  Intended for use with [`click`][CLICK] and
107)     when `PKG` provides a command-line tool `PKG` and when logs from
108)     that package should show up as output of the command-line tool.
109) 
110)     Essentially, this prepends certain short strings to the log message
111)     lines to make them readable as standard error output.
112) 
113)     Because this log output is intended to be displayed on standard
114)     error as high-level diagnostic output, you are strongly discouraged
115)     from changing the output format to include more tokens besides the
116)     log message.  Use a dedicated log file handler instead, without this
117)     formatter.
118) 
119)     [CLICK]: https://pypi.org/projects/click/
120) 
121)     """
122) 
123)     def __init__(
124)         self,
125)         *,
126)         prog_name: str = PROG_NAME,
127)         package_name: str | None = None,
128)     ) -> None:
129)         self.prog_name = prog_name
130)         self.package_name = (
131)             package_name
132)             if package_name is not None
133)             else prog_name.lower().replace(' ', '_').replace('-', '_')
134)         )
135) 
136)     def format(self, record: logging.LogRecord) -> str:
137)         """Format a log record suitably for standard error console output.
138) 
139)         Prepend the formatted string `"PROG_NAME: LABEL"` to each line
140)         of the message, where `PROG_NAME` is the program name, and
141)         `LABEL` depends on the record's level and on the logger name as
142)         follows:
143) 
144)           * For records at level [`logging.DEBUG`][], `LABEL` is
145)             `"Debug: "`.
146)           * For records at level [`logging.INFO`][], `LABEL` is the
147)             empty string.
148)           * For records at level [`logging.WARNING`][], `LABEL` is
149)             `"Deprecation warning: "` if the logger is named
150)             `PKG.deprecation` (where `PKG` is the package name), else
151)             `"Warning: "`.
152)           * For records at level [`logging.ERROR`][] and
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

153)             [`logging.CRITICAL`][] `"Error: "`, `LABEL` is the empty
154)             string.
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

155) 
156)         The level indication strings at level `WARNING` or above are
157)         highlighted.  Use [`click.echo`][] to output them and remove
158)         color output if necessary.
159) 
160)         Args:
161)             record: A log record.
162) 
163)         Returns:
164)             A formatted log record.
165) 
166)         Raises:
167)             AssertionError:
168)                 The log level is not supported.
169) 
170)         """
171)         preliminary_result = record.getMessage()
172)         prefix = f'{self.prog_name}: '
173)         if record.levelname == 'DEBUG':  # pragma: no cover
174)             level_indicator = 'Debug: '
175)         elif record.levelname == 'INFO':
176)             level_indicator = ''
177)         elif record.levelname == 'WARNING':
178)             level_indicator = (
179)                 f'{click.style("Deprecation warning", bold=True)}: '
180)                 if record.name.endswith('.deprecation')
181)                 else f'{click.style("Warning", bold=True)}: '
182)             )
183)         elif record.levelname in {'ERROR', 'CRITICAL'}:
184)             level_indicator = ''
185)         else:  # pragma: no cover
186)             msg = f'Unsupported logging level: {record.levelname}'
187)             raise AssertionError(msg)
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

188)         parts = [
189)             ''.join(
190)                 prefix + level_indicator + line
191)                 for line in preliminary_result.splitlines(True)  # noqa: FBT003
192)             )
193)         ]
194)         if record.exc_info:
195)             parts.append(self.formatException(record.exc_info) + '\n')
196)         return ''.join(parts)
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

197) 
198) 
199) class StandardCLILogging:
200)     """Set up CLI logging handlers upon instantiation."""
201) 
202)     prog_name = PROG_NAME
203)     package_name = PROG_NAME.lower().replace(' ', '_').replace('-', '_')
204)     cli_formatter = CLIofPackageFormatter(
205)         prog_name=prog_name, package_name=package_name
206)     )
207)     cli_handler = ClickEchoStderrHandler()
208)     cli_handler.addFilter(logging.Filter(name=package_name))
209)     cli_handler.setFormatter(cli_formatter)
210)     cli_handler.setLevel(logging.WARNING)
211)     warnings_handler = ClickEchoStderrHandler()
212)     warnings_handler.addFilter(logging.Filter(name='py.warnings'))
213)     warnings_handler.setFormatter(cli_formatter)
214)     warnings_handler.setLevel(logging.WARNING)
215) 
216)     @classmethod
217)     def ensure_standard_logging(cls) -> StandardLoggingContextManager:
218)         """Return a context manager to ensure standard logging is set up."""
219)         return StandardLoggingContextManager(
220)             handler=cls.cli_handler,
221)             root_logger=cls.package_name,
222)         )
223) 
224)     @classmethod
225)     def ensure_standard_warnings_logging(
226)         cls,
227)     ) -> StandardWarningsLoggingContextManager:
228)         """Return a context manager to ensure warnings logging is set up."""
229)         return StandardWarningsLoggingContextManager(
230)             handler=cls.warnings_handler,
231)         )
232) 
233) 
234) class StandardLoggingContextManager:
235)     """A reentrant context manager setting up standard CLI logging.
236) 
237)     Ensures that the given handler (defaulting to the CLI logging
238)     handler) is added to the named logger (defaulting to the root
239)     logger), and if it had to be added, then that it will be removed
240)     upon exiting the context.
241) 
242)     Reentrant, but not thread safe, because it temporarily modifies
243)     global state.
244) 
245)     """
246) 
247)     def __init__(
248)         self,
249)         handler: logging.Handler,
250)         root_logger: str | None = None,
251)     ) -> None:
252)         self.handler = handler
253)         self.root_logger_name = root_logger
254)         self.base_logger = logging.getLogger(self.root_logger_name)
255)         self.action_required: MutableSequence[bool] = collections.deque()
256) 
257)     def __enter__(self) -> Self:
258)         self.action_required.append(
259)             self.handler not in self.base_logger.handlers
260)         )
261)         if self.action_required[-1]:
262)             self.base_logger.addHandler(self.handler)
263)         return self
264) 
265)     def __exit__(
266)         self,
267)         exc_type: type[BaseException] | None,
268)         exc_value: BaseException | None,
269)         exc_tb: types.TracebackType | None,
270)     ) -> Literal[False]:
271)         if self.action_required[-1]:
272)             self.base_logger.removeHandler(self.handler)
273)         self.action_required.pop()
274)         return False
275) 
276) 
277) class StandardWarningsLoggingContextManager(StandardLoggingContextManager):
278)     """A reentrant context manager setting up standard warnings logging.
279) 
280)     Ensures that warnings are being diverted to the logging system, and
281)     that the given handler (defaulting to the CLI logging handler) is
282)     added to the warnings logger. If the handler had to be added, then
283)     it will be removed upon exiting the context.
284) 
285)     Reentrant, but not thread safe, because it temporarily modifies
286)     global state.
287) 
288)     """
289) 
290)     def __init__(
291)         self,
292)         handler: logging.Handler,
293)     ) -> None:
294)         super().__init__(handler=handler, root_logger='py.warnings')
295)         self.stack: MutableSequence[
296)             tuple[
297)                 Callable[
298)                     [
299)                         type[BaseException] | None,
300)                         BaseException | None,
301)                         types.TracebackType | None,
302)                     ],
303)                     None,
304)                 ],
305)                 Callable[
306)                     [
307)                         str | Warning,
308)                         type[Warning],
309)                         str,
310)                         int,
311)                         TextIO | None,
312)                         str | None,
313)                     ],
314)                     None,
315)                 ],
316)             ]
317)         ] = collections.deque()
318) 
319)     def __enter__(self) -> Self:
320)         def showwarning(  # noqa: PLR0913,PLR0917
321)             message: str | Warning,
322)             category: type[Warning],
323)             filename: str,
324)             lineno: int,
325)             file: TextIO | None = None,
326)             line: str | None = None,
327)         ) -> None:
328)             if file is not None:  # pragma: no cover
329)                 self.stack[0][1](
330)                     message, category, filename, lineno, file, line
331)                 )
332)             else:
333)                 logging.getLogger('py.warnings').warning(
334)                     str(
335)                         warnings.formatwarning(
336)                             message, category, filename, lineno, line
337)                         )
338)                     )
339)                 )
340) 
341)         ctx = warnings.catch_warnings()
342)         exit_func = ctx.__exit__
343)         ctx.__enter__()
344)         self.stack.append((exit_func, warnings.showwarning))
345)         warnings.showwarning = showwarning
346)         return super().__enter__()
347) 
348)     def __exit__(
349)         self,
350)         exc_type: type[BaseException] | None,
351)         exc_value: BaseException | None,
352)         exc_tb: types.TracebackType | None,
353)     ) -> Literal[False]:
354)         ret = super().__exit__(exc_type, exc_value, exc_tb)
355)         val = self.stack.pop()[0](exc_type, exc_value, exc_tb)
356)         assert not val
357)         return ret
358) 
359) 
360) P = ParamSpec('P')
361) R = TypeVar('R')
362) 
363) 
Marco Ricci Fix usage of `--debug`, `--...

Marco Ricci authored 3 weeks ago

364) def adjust_logging_level(
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

365)     ctx: click.Context,
366)     /,
367)     param: click.Parameter | None = None,
Marco Ricci Fix usage of `--debug`, `--...

Marco Ricci authored 3 weeks ago

368)     value: int | None = None,
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

369) ) -> None:
Marco Ricci Fix usage of `--debug`, `--...

Marco Ricci authored 3 weeks ago

370)     """Change the logs that are emitted to standard error.
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

371) 
372)     This modifies the [`StandardCLILogging`][] settings such that log
Marco Ricci Fix usage of `--debug`, `--...

Marco Ricci authored 3 weeks ago

373)     records at the respective level are emitted, based on the `param`
374)     and the `value`.
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

375) 
376)     """
Marco Ricci Fix usage of `--debug`, `--...

Marco Ricci authored 3 weeks ago

377)     # Note: If multiple options use this callback, then we will be
378)     # called multiple times.  Ensure the runs are idempotent.
379)     if param is None or value is None or ctx.resilient_parsing:
380)         return
381)     StandardCLILogging.cli_handler.setLevel(value)
382)     logging.getLogger(StandardCLILogging.package_name).setLevel(value)
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

383) 
384) 
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

385) # Option parsing and grouping
386) # ===========================
387) 
388) 
389) class OptionGroupOption(click.Option):
390)     """A [`click.Option`][] with an associated group name and group epilog.
391) 
392)     Used by [`CommandWithHelpGroups`][] to print help sections.  Each
393)     subclass contains its own group name and epilog.
394) 
395)     Attributes:
396)         option_group_name:
397)             The name of the option group.  Used as a heading on the help
398)             text for options in this section.
399)         epilog:
400)             An epilog to print after listing the options in this
401)             section.
402) 
403)     """
404) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

405)     option_group_name: object = ''
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

406)     """"""
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

407)     epilog: object = ''
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

408)     """"""
409) 
410)     def __init__(self, *args: Any, **kwargs: Any) -> None:  # noqa: ANN401
411)         if self.__class__ == __class__:  # type: ignore[name-defined]
412)             raise NotImplementedError
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

413)         # Though click 8.1 mostly defers help text processing until the
414)         # `BaseCommand.format_*` methods are called, the Option
415)         # constructor still preprocesses the help text, and asserts that
416)         # the help text is a string.  Work around this by removing the
417)         # help text from the constructor arguments and re-adding it,
418)         # unprocessed, after constructor finishes.
419)         unset = object()
420)         help = kwargs.pop('help', unset)  # noqa: A001
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

421)         super().__init__(*args, **kwargs)
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

422)         if help is not unset:  # pragma: no branch
423)             self.help = help
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

424) 
425) 
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

426) class StandardOption(OptionGroupOption):
427)     pass
428) 
429) 
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

430) class CommandWithHelpGroups(click.Command):
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

431)     """A [`click.Command`][] with support for some help text customizations.
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

432) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

433)     Supports help/option groups, group epilogs, and help text objects
434)     (objects that stringify to help texts).  The latter is primarily
435)     used to implement translations.
436) 
437)     Inspired by [a comment on `pallets/click#373`][CLICK_ISSUE] for
438)     help/option group support, and further modified to include group
439)     epilogs and help text objects.
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

440) 
441)     [CLICK_ISSUE]: https://github.com/pallets/click/issues/373#issuecomment-515293746
442) 
443)     """
444) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

445)     @staticmethod
446)     def _text(text: object, /) -> str:
447)         if isinstance(text, (list, tuple)):
448)             return '\n\n'.join(str(x) for x in text)
449)         return str(text)
450) 
451)     def collect_usage_pieces(self, ctx: click.Context) -> list[str]:
452)         """Return the pieces for the usage string.
453) 
454)         Based on code from click 8.1.  Subject to the following license
455)         (3-clause BSD license):
456) 
457)             Copyright 2024 Pallets
458) 
459)             Redistribution and use in source and binary forms, with or
460)             without modification, are permitted provided that the
461)             following conditions are met:
462) 
463)              1. Redistributions of source code must retain the above
464)                 copyright notice, this list of conditions and the
465)                 following disclaimer.
466) 
467)              2. Redistributions in binary form must reproduce the above
468)                 copyright notice, this list of conditions and the
469)                 following disclaimer in the documentation and/or other
470)                 materials provided with the distribution.
471) 
472)              3. Neither the name of the copyright holder nor the names
473)                 of its contributors may be used to endorse or promote
474)                 products derived from this software without specific
475)                 prior written permission.
476) 
477)             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
478)             CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
479)             INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
480)             MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
481)             DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
482)             CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
483)             SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
484)             NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
485)             LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
486)             HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
487)             CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
488)             OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
489)             SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
490) 
491)         Modifications are marked with respective comments.  They too are
492)         released under the same license above.  The original code did
493)         not contain any "noqa" or "pragma" comments.
494) 
495)         Args:
496)             ctx:
497)                 The click context.
498) 
499)         """
500)         rv = [str(self.options_metavar)] if self.options_metavar else []
501)         for param in self.get_params(ctx):
502)             rv.extend(str(x) for x in param.get_usage_pieces(ctx))
503)         return rv
504) 
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

505)     def get_help_option(
506)         self,
507)         ctx: click.Context,
508)     ) -> click.Option | None:
509)         """Return a standard help option object.
510) 
511)         Based on code from click 8.1.  Subject to the following license
512)         (3-clause BSD license):
513) 
514)             Copyright 2024 Pallets
515) 
516)             Redistribution and use in source and binary forms, with or
517)             without modification, are permitted provided that the
518)             following conditions are met:
519) 
520)              1. Redistributions of source code must retain the above
521)                 copyright notice, this list of conditions and the
522)                 following disclaimer.
523) 
524)              2. Redistributions in binary form must reproduce the above
525)                 copyright notice, this list of conditions and the
526)                 following disclaimer in the documentation and/or other
527)                 materials provided with the distribution.
528) 
529)              3. Neither the name of the copyright holder nor the names
530)                 of its contributors may be used to endorse or promote
531)                 products derived from this software without specific
532)                 prior written permission.
533) 
534)             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
535)             CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
536)             INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
537)             MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
538)             DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
539)             CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
540)             SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
541)             NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
542)             LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
543)             HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
544)             CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
545)             OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
546)             SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
547) 
548)         Modifications are marked with respective comments.  They too are
549)         released under the same license above.  The original code did
550)         not contain any "noqa" or "pragma" comments.
551) 
552)         Args:
553)             ctx:
554)                 The click context.
555) 
556)         """
557)         help_options = self.get_help_option_names(ctx)
558) 
559)         if not help_options or not self.add_help_option:  # pragma: no cover
560)             return None
561) 
562)         def show_help(
563)             ctx: click.Context,
564)             param: click.Parameter,  # noqa: ARG001
565)             value: str,
566)         ) -> None:
567)             if value and not ctx.resilient_parsing:
568)                 click.echo(ctx.get_help(), color=ctx.color)
569)                 ctx.exit()
570) 
571)         # Modified from click 8.1: We use StandardOption and a non-str
572)         # object as the help string.
573)         return StandardOption(
574)             help_options,
575)             is_flag=True,
576)             is_eager=True,
577)             expose_value=False,
578)             callback=show_help,
579)             help=_msg.TranslatedString(_msg.Label.HELP_OPTION_HELP_TEXT),
580)         )
581) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

582)     def get_short_help_str(
583)         self,
584)         limit: int = 45,
585)     ) -> str:
586)         """Return the short help string for a command.
587) 
588)         If only a long help string is given, shorten it.
589) 
590)         Based on code from click 8.1.  Subject to the following license
591)         (3-clause BSD license):
592) 
593)             Copyright 2024 Pallets
594) 
595)             Redistribution and use in source and binary forms, with or
596)             without modification, are permitted provided that the
597)             following conditions are met:
598) 
599)              1. Redistributions of source code must retain the above
600)                 copyright notice, this list of conditions and the
601)                 following disclaimer.
602) 
603)              2. Redistributions in binary form must reproduce the above
604)                 copyright notice, this list of conditions and the
605)                 following disclaimer in the documentation and/or other
606)                 materials provided with the distribution.
607) 
608)              3. Neither the name of the copyright holder nor the names
609)                 of its contributors may be used to endorse or promote
610)                 products derived from this software without specific
611)                 prior written permission.
612) 
613)             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
614)             CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
615)             INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
616)             MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
617)             DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
618)             CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
619)             SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
620)             NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
621)             LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
622)             HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
623)             CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
624)             OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
625)             SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
626) 
627)         Modifications are marked with respective comments.  They too are
628)         released under the same license above.  The original code did
629)         not contain any "noqa" or "pragma" comments.
630) 
631)         Args:
632)             limit:
633)                 The maximum width of the short help string.
634) 
635)         """
636)         # Modification against click 8.1: Call `_text()` on `self.help`
637)         # to allow help texts to be general objects, not just strings.
638)         # Used to implement translatable strings, as objects that
639)         # stringify to the translation.
640)         if self.short_help:  # pragma: no cover
641)             text = inspect.cleandoc(self._text(self.short_help))
642)         elif self.help:
643)             text = click.utils.make_default_short_help(
644)                 self._text(self.help), limit
645)             )
646)         else:  # pragma: no cover
647)             text = ''
648)         if self.deprecated:  # pragma: no cover
649)             # Modification against click 8.1: The translated string is
650)             # looked up in the derivepassphrase message domain, not the
651)             # gettext default domain.
652)             text = str(
653)                 _msg.TranslatedString(_msg.Label.DEPRECATED_COMMAND_LABEL)
654)             ).format(text=text)
655)         return text.strip()
656) 
657)     def format_help_text(
658)         self,
659)         ctx: click.Context,
660)         formatter: click.HelpFormatter,
661)     ) -> None:
662)         """Format the help text prologue, if any.
663) 
664)         Based on code from click 8.1.  Subject to the following license
665)         (3-clause BSD license):
666) 
667)             Copyright 2024 Pallets
668) 
669)             Redistribution and use in source and binary forms, with or
670)             without modification, are permitted provided that the
671)             following conditions are met:
672) 
673)              1. Redistributions of source code must retain the above
674)                 copyright notice, this list of conditions and the
675)                 following disclaimer.
676) 
677)              2. Redistributions in binary form must reproduce the above
678)                 copyright notice, this list of conditions and the
679)                 following disclaimer in the documentation and/or other
680)                 materials provided with the distribution.
681) 
682)              3. Neither the name of the copyright holder nor the names
683)                 of its contributors may be used to endorse or promote
684)                 products derived from this software without specific
685)                 prior written permission.
686) 
687)             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
688)             CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
689)             INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
690)             MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
691)             DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
692)             CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
693)             SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
694)             NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
695)             LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
696)             HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
697)             CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
698)             OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
699)             SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
700) 
701)         Modifications are marked with respective comments.  They too are
702)         released under the same license above.  The original code did
703)         not contain any "noqa" or "pragma" comments.
704) 
705)         Args:
706)             ctx:
707)                 The click context.
708)             formatter:
709)                 The formatter for the `--help` listing.
710) 
711)         """
712)         del ctx
713)         # Modification against click 8.1: Call `_text()` on `self.help`
714)         # to allow help texts to be general objects, not just strings.
715)         # Used to implement translatable strings, as objects that
716)         # stringify to the translation.
717)         text = (
718)             inspect.cleandoc(self._text(self.help).partition('\f')[0])
719)             if self.help is not None
720)             else ''
721)         )
722)         if self.deprecated:  # pragma: no cover
723)             # Modification against click 8.1: The translated string is
724)             # looked up in the derivepassphrase message domain, not the
725)             # gettext default domain.
726)             text = str(
727)                 _msg.TranslatedString(_msg.Label.DEPRECATED_COMMAND_LABEL)
728)             ).format(text=text)
729)         if text:  # pragma: no branch
730)             formatter.write_paragraph()
731)             with formatter.indentation():
732)                 formatter.write_text(text)
733) 
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

734)     def format_options(
735)         self,
736)         ctx: click.Context,
737)         formatter: click.HelpFormatter,
738)     ) -> None:
739)         r"""Format options on the help listing, grouped into sections.
740) 
741)         This is a callback for [`click.Command.get_help`][] that
742)         implements the `--help` listing, by calling appropriate methods
743)         of the `formatter`.  We list all options (like the base
744)         implementation), but grouped into sections according to the
745)         concrete [`click.Option`][] subclass being used.  If the option
746)         is an instance of some subclass of [`OptionGroupOption`][], then
747)         the section heading and the epilog are taken from the
748)         [`option_group_name`] [OptionGroupOption.option_group_name] and
749)         [`epilog`] [OptionGroupOption.epilog] attributes; otherwise, the
750)         section heading is "Options" (or "Other options" if there are
751)         other option groups) and the epilog is empty.
752) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

753)         We unconditionally call [`format_commands`][], and rely on it to
754)         act as a no-op if we aren't actually a [`click.MultiCommand`][].
755) 
756)         Based on code from click 8.1.  Subject to the following license
757)         (3-clause BSD license):
758) 
759)             Copyright 2024 Pallets
760) 
761)             Redistribution and use in source and binary forms, with or
762)             without modification, are permitted provided that the
763)             following conditions are met:
764) 
765)              1. Redistributions of source code must retain the above
766)                 copyright notice, this list of conditions and the
767)                 following disclaimer.
768) 
769)              2. Redistributions in binary form must reproduce the above
770)                 copyright notice, this list of conditions and the
771)                 following disclaimer in the documentation and/or other
772)                 materials provided with the distribution.
773) 
774)              3. Neither the name of the copyright holder nor the names
775)                 of its contributors may be used to endorse or promote
776)                 products derived from this software without specific
777)                 prior written permission.
778) 
779)             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
780)             CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
781)             INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
782)             MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
783)             DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
784)             CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
785)             SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
786)             NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
787)             LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
788)             HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
789)             CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
790)             OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
791)             SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
792) 
793)         Modifications are released under the same license above.
794) 
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

795)         Args:
796)             ctx:
797)                 The click context.
798)             formatter:
799)                 The formatter for the `--help` listing.
800) 
801)         """
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

802)         default_group_name = ''
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

803)         help_records: dict[str, list[tuple[str, str]]] = {}
804)         epilogs: dict[str, str] = {}
805)         params = self.params[:]
806)         if (  # pragma: no branch
807)             (help_opt := self.get_help_option(ctx)) is not None
808)             and help_opt not in params
809)         ):
810)             params.append(help_opt)
811)         for param in params:
812)             rec = param.get_help_record(ctx)
813)             if rec is not None:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

814)                 rec = (rec[0], self._text(rec[1]))
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

815)                 if isinstance(param, OptionGroupOption):
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

816)                     group_name = self._text(param.option_group_name)
817)                     epilogs.setdefault(group_name, self._text(param.epilog))
Marco Ricci Fix coverage

Marco Ricci authored 1 week ago

818)                 else:  # pragma: no cover
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

819)                     group_name = default_group_name
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

820)                 help_records.setdefault(group_name, []).append(rec)
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

821)         if default_group_name in help_records:  # pragma: no branch
822)             default_group = help_records.pop(default_group_name)
823)             default_group_label = (
824)                 _msg.Label.OTHER_OPTIONS_LABEL
825)                 if len(default_group) > 1
826)                 else _msg.Label.OPTIONS_LABEL
827)             )
828)             default_group_name = self._text(
829)                 _msg.TranslatedString(default_group_label)
830)             )
831)             help_records[default_group_name] = default_group
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

832)         for group_name, records in help_records.items():
833)             with formatter.section(group_name):
834)                 formatter.write_dl(records)
835)             epilog = inspect.cleandoc(epilogs.get(group_name, ''))
836)             if epilog:
837)                 formatter.write_paragraph()
838)                 with formatter.indentation():
839)                     formatter.write_text(epilog)
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

840)         self.format_commands(ctx, formatter)
841) 
842)     def format_commands(
843)         self,
844)         ctx: click.Context,
845)         formatter: click.HelpFormatter,
846)     ) -> None:
847)         """Format the subcommands, if any.
848) 
849)         If called on a command object that isn't derived from
850)         [`click.MultiCommand`][], then do nothing.
851) 
852)         Based on code from click 8.1.  Subject to the following license
853)         (3-clause BSD license):
854) 
855)             Copyright 2024 Pallets
856) 
857)             Redistribution and use in source and binary forms, with or
858)             without modification, are permitted provided that the
859)             following conditions are met:
860) 
861)              1. Redistributions of source code must retain the above
862)                 copyright notice, this list of conditions and the
863)                 following disclaimer.
864) 
865)              2. Redistributions in binary form must reproduce the above
866)                 copyright notice, this list of conditions and the
867)                 following disclaimer in the documentation and/or other
868)                 materials provided with the distribution.
869) 
870)              3. Neither the name of the copyright holder nor the names
871)                 of its contributors may be used to endorse or promote
872)                 products derived from this software without specific
873)                 prior written permission.
874) 
875)             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
876)             CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
877)             INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
878)             MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
879)             DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
880)             CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
881)             SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
882)             NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
883)             LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
884)             HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
885)             CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
886)             OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
887)             SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
888) 
889)         Modifications are marked with respective comments.  They too are
890)         released under the same license above.  The original code did
891)         not contain any "noqa" or "pragma" comments.
892) 
893)         Args:
894)             ctx:
895)                 The click context.
896)             formatter:
897)                 The formatter for the `--help` listing.
898) 
899)         """
900)         if not isinstance(self, click.MultiCommand):
901)             return
902)         commands: list[tuple[str, click.Command]] = []
903)         for subcommand in self.list_commands(ctx):
904)             cmd = self.get_command(ctx, subcommand)
905)             if cmd is None or cmd.hidden:  # pragma: no cover
906)                 continue
907)             commands.append((subcommand, cmd))
908)         if commands:  # pragma: no branch
909)             longest_command = max((cmd[0] for cmd in commands), key=len)
910)             limit = formatter.width - 6 - len(longest_command)
911)             rows: list[tuple[str, str]] = []
912)             for subcommand, cmd in commands:
913)                 help_str = self._text(cmd.get_short_help_str(limit) or '')
914)                 rows.append((subcommand, help_str))
915)             if rows:  # pragma: no branch
916)                 commands_label = self._text(
917)                     _msg.TranslatedString(_msg.Label.COMMANDS_LABEL)
918)                 )
919)                 with formatter.section(commands_label):
920)                     formatter.write_dl(rows)
921) 
922)     def format_epilog(
923)         self,
924)         ctx: click.Context,
925)         formatter: click.HelpFormatter,
926)     ) -> None:
927)         """Format the epilog, if any.
928) 
929)         Based on code from click 8.1.  Subject to the following license
930)         (3-clause BSD license):
931) 
932)             Copyright 2024 Pallets
933) 
934)             Redistribution and use in source and binary forms, with or
935)             without modification, are permitted provided that the
936)             following conditions are met:
937) 
938)              1. Redistributions of source code must retain the above
939)                 copyright notice, this list of conditions and the
940)                 following disclaimer.
941) 
942)              2. Redistributions in binary form must reproduce the above
943)                 copyright notice, this list of conditions and the
944)                 following disclaimer in the documentation and/or other
945)                 materials provided with the distribution.
946) 
947)              3. Neither the name of the copyright holder nor the names
948)                 of its contributors may be used to endorse or promote
949)                 products derived from this software without specific
950)                 prior written permission.
951) 
952)             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
953)             CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
954)             INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
955)             MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
956)             DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
957)             CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
958)             SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
959)             NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
960)             LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
961)             HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
962)             CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
963)             OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
964)             SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
965) 
966)         Modifications are marked with respective comments.  They too are
967)         released under the same license above.
968) 
969)         Args:
970)             ctx:
971)                 The click context.
972)             formatter:
973)                 The formatter for the `--help` listing.
974) 
975)         """
976)         del ctx
977)         if self.epilog:  # pragma: no branch
978)             # Modification against click 8.1: Call `str()` on
979)             # `self.epilog` to allow help texts to be general objects,
980)             # not just strings.  Used to implement translatable strings,
981)             # as objects that stringify to the translation.
982)             epilog = inspect.cleandoc(self._text(self.epilog))
983)             formatter.write_paragraph()
984)             with formatter.indentation():
985)                 formatter.write_text(epilog)
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

986) 
987) 
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

988) def version_option_callback(
989)     ctx: click.Context,
990)     param: click.Parameter,
991)     value: bool,  # noqa: FBT001
Marco Ricci Fix coverage

Marco Ricci authored 1 week ago

992) ) -> None:  # pragma: no cover
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

993)     del param
994)     if value and not ctx.resilient_parsing:
995)         click.echo(
996)             str(
997)                 _msg.TranslatedString(
998)                     _msg.Label.VERSION_INFO_TEXT,
999)                     PROG_NAME=PROG_NAME,
1000)                     __version__=__version__,
1001)                 )
1002)             ),
1003)         )
1004)         ctx.exit()
1005) 
1006) 
1007) def version_option(f: Callable[P, R]) -> Callable[P, R]:
1008)     return click.option(
1009)         '--version',
1010)         is_flag=True,
1011)         is_eager=True,
1012)         expose_value=False,
1013)         callback=version_option_callback,
1014)         cls=StandardOption,
1015)         help=_msg.TranslatedString(_msg.Label.VERSION_OPTION_HELP_TEXT),
1016)     )(f)
1017) 
1018) 
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1019) class LoggingOption(OptionGroupOption):
1020)     """Logging options for the CLI."""
1021) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1022)     option_group_name = _msg.TranslatedString(_msg.Label.LOGGING_LABEL)
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1023)     epilog = ''
1024) 
1025) 
Marco Ricci Fix usage of `--debug`, `--...

Marco Ricci authored 3 weeks ago

1026) debug_option = click.option(
1027)     '--debug',
1028)     'logging_level',
1029)     is_flag=True,
1030)     flag_value=logging.DEBUG,
1031)     expose_value=False,
1032)     callback=adjust_logging_level,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1033)     help=_msg.TranslatedString(_msg.Label.DEBUG_OPTION_HELP_TEXT),
Marco Ricci Fix usage of `--debug`, `--...

Marco Ricci authored 3 weeks ago

1034)     cls=LoggingOption,
1035) )
1036) verbose_option = click.option(
1037)     '-v',
1038)     '--verbose',
1039)     'logging_level',
1040)     is_flag=True,
1041)     flag_value=logging.INFO,
1042)     expose_value=False,
1043)     callback=adjust_logging_level,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1044)     help=_msg.TranslatedString(_msg.Label.VERBOSE_OPTION_HELP_TEXT),
Marco Ricci Fix usage of `--debug`, `--...

Marco Ricci authored 3 weeks ago

1045)     cls=LoggingOption,
1046) )
1047) quiet_option = click.option(
1048)     '-q',
1049)     '--quiet',
1050)     'logging_level',
1051)     is_flag=True,
1052)     flag_value=logging.ERROR,
1053)     expose_value=False,
1054)     callback=adjust_logging_level,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1055)     help=_msg.TranslatedString(_msg.Label.QUIET_OPTION_HELP_TEXT),
Marco Ricci Fix usage of `--debug`, `--...

Marco Ricci authored 3 weeks ago

1056)     cls=LoggingOption,
1057) )
1058) 
1059) 
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1060) def standard_logging_options(f: Callable[P, R]) -> Callable[P, R]:
1061)     """Decorate the function with standard logging click options.
1062) 
1063)     Adds the three click options `-v`/`--verbose`, `-q`/`--quiet` and
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

1064)     `--debug`, which calls back into the [`adjust_logging_level`][]
1065)     function (with different argument values).
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1066) 
1067)     Args:
1068)         f: A callable to decorate.
1069) 
1070)     Returns:
1071)         The decorated callable.
1072) 
1073)     """
Marco Ricci Fix usage of `--debug`, `--...

Marco Ricci authored 3 weeks ago

1074)     return debug_option(verbose_option(quiet_option(f)))
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1075) 
1076) 
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1077) # Top-level
1078) # =========
1079) 
1080) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1081) class _DefaultToVaultGroup(CommandWithHelpGroups, click.Group):
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1082)     """A helper class to implement the default-to-"vault"-subcommand behavior.
1083) 
1084)     Modifies internal [`click.MultiCommand`][] methods, and thus is both
1085)     an implementation detail and a kludge.
1086) 
1087)     """
1088) 
1089)     def resolve_command(
1090)         self, ctx: click.Context, args: list[str]
1091)     ) -> tuple[str | None, click.Command | None, list[str]]:
1092)         """Resolve a command, but default to "vault" instead of erroring out.
1093) 
1094)         Based on code from click 8.1, which appears to be essentially
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1095)         untouched since at least click 3.2.  Subject to the following
1096)         license (3-clause BSD license):
1097) 
1098)             Copyright 2024 Pallets
1099) 
1100)             Redistribution and use in source and binary forms, with or
1101)             without modification, are permitted provided that the following
1102)             conditions are met:
1103) 
1104)              1. Redistributions of source code must retain the above
1105)                 copyright notice, this list of conditions and the following
1106)                 disclaimer.
1107) 
1108)              2. Redistributions in binary form must reproduce the above
1109)                 copyright notice, this list of conditions and the following
1110)                 disclaimer in the documentation and/or other materials
1111)                 provided with the distribution.
1112) 
1113)              3. Neither the name of the copyright holder nor the names of
1114)                 its contributors may be used to endorse or promote products
1115)                 derived from this software without specific prior written
1116)                 permission.
1117) 
1118)             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
1119)             CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
1120)             INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1121)             MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1122)             DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
1123)             CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1124)             SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1125)             LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
1126)             USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
1127)             AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1128)             LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
1129)             IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
1130)             THE POSSIBILITY OF SUCH DAMAGE.
1131) 
1132)         Modifications to this routine are marked with "modifications for
1133)         derivepassphrase".  Furthermore, all "pragma" and "noqa" comments
1134)         are also modifications for derivepassphrase.
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1135) 
1136)         """
1137)         cmd_name = click.utils.make_str(args[0])
1138) 
1139)         # Get the command
1140)         cmd = self.get_command(ctx, cmd_name)
1141) 
1142)         # If we can't find the command but there is a normalization
1143)         # function available, we try with that one.
1144)         if (  # pragma: no cover
1145)             cmd is None and ctx.token_normalize_func is not None
1146)         ):
1147)             cmd_name = ctx.token_normalize_func(cmd_name)
1148)             cmd = self.get_command(ctx, cmd_name)
1149) 
1150)         # If we don't find the command we want to show an error message
1151)         # to the user that it was not provided.  However, there is
1152)         # something else we should do: if the first argument looks like
1153)         # an option we want to kick off parsing again for arguments to
1154)         # resolve things like --help which now should go to the main
1155)         # place.
1156)         if cmd is None and not ctx.resilient_parsing:
1157)             if click.parser.split_opt(cmd_name)[0]:
1158)                 self.parse_args(ctx, ctx.args)
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1159)             ####
1160)             # BEGIN modifications for derivepassphrase
1161)             #
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1162)             # Instead of calling ctx.fail here, default to "vault", and
1163)             # issue a deprecation warning.
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1164)             deprecation = logging.getLogger(f'{PROG_NAME}.deprecation')
1165)             deprecation.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1166)                 _msg.TranslatedString(
1167)                     _msg.WarnMsgTemplate.V10_SUBCOMMAND_REQUIRED
1168)                 )
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1169)             )
1170)             cmd_name = 'vault'
1171)             cmd = self.get_command(ctx, cmd_name)
1172)             assert cmd is not None, 'Mandatory subcommand "vault" missing!'
1173)             args = [cmd_name, *args]
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1174)             #
1175)             # END modifications for derivepassphrase
1176)             ####
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1177)         return cmd_name if cmd else None, cmd, args[1:]  # noqa: DOC201
1178) 
1179) 
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1180) class _TopLevelCLIEntryPoint(_DefaultToVaultGroup):
1181)     """A minor variation of _DefaultToVaultGroup for the top-level command.
1182) 
1183)     When called as a function, this sets up the environment properly
1184)     before invoking the actual callbacks.  Currently, this means setting
1185)     up the logging subsystem and the delegation of Python warnings to
1186)     the logging subsystem.
1187) 
1188)     The environment setup can be bypassed by calling the `.main` method
1189)     directly.
1190) 
1191)     """
1192) 
1193)     def __call__(  # pragma: no cover
1194)         self,
1195)         *args: Any,  # noqa: ANN401
1196)         **kwargs: Any,  # noqa: ANN401
1197)     ) -> Any:  # noqa: ANN401
1198)         """"""  # noqa: D419
1199)         # Coverage testing is done with the `click.testing` module,
1200)         # which does not use the `__call__` shortcut.  So it is normal
1201)         # that this function is never called, and thus should be
1202)         # excluded from coverage.
1203)         with (
1204)             StandardCLILogging.ensure_standard_logging(),
1205)             StandardCLILogging.ensure_standard_warnings_logging(),
1206)         ):
1207)             return self.main(*args, **kwargs)
1208) 
1209) 
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1210) @click.group(
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1211)     context_settings={
1212)         'help_option_names': ['-h', '--help'],
1213)         'ignore_unknown_options': True,
1214)         'allow_interspersed_args': False,
1215)     },
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1216)     epilog=_msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_EPILOG_01),
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1217)     invoke_without_command=True,
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1218)     cls=_TopLevelCLIEntryPoint,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1219)     help=(
1220)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_01),
1221)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_02),
1222)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_03),
1223)     ),
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1224) )
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

1225) @version_option
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1226) @standard_logging_options
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1227) @click.pass_context
1228) def derivepassphrase(ctx: click.Context, /) -> None:
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1229)     """Derive a strong passphrase, deterministically, from a master secret.
1230) 
1231)     This is a [`click`][CLICK]-powered command-line interface function,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1232)     and not intended for programmatic use.  See the derivepassphrase(1)
1233)     manpage for full documentation of the interface.  (See also
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1234)     [`click.testing.CliRunner`][] for controlled, programmatic
1235)     invocation.)
1236) 
Marco Ricci Update all URLs to stable a...

Marco Ricci authored 3 months ago

1237)     [CLICK]: https://pypi.org/package/click/
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1238) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1239)     """
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1240)     deprecation = logging.getLogger(f'{PROG_NAME}.deprecation')
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1241)     if ctx.invoked_subcommand is None:
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1242)         deprecation.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1243)             _msg.TranslatedString(_msg.WarnMsgTemplate.V10_SUBCOMMAND_REQUIRED)
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1244)         )
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1245)         # See definition of click.Group.invoke, non-chained case.
1246)         with ctx:
1247)             sub_ctx = derivepassphrase_vault.make_context(
1248)                 'vault', ctx.args, parent=ctx
1249)             )
1250)             with sub_ctx:
1251)                 return derivepassphrase_vault.invoke(sub_ctx)
1252)     return None
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1253) 
1254) 
1255) # Exporter
1256) # ========
1257) 
1258) 
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1259) @derivepassphrase.group(
1260)     'export',
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1261)     context_settings={
1262)         'help_option_names': ['-h', '--help'],
1263)         'ignore_unknown_options': True,
1264)         'allow_interspersed_args': False,
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1265)     },
1266)     invoke_without_command=True,
1267)     cls=_DefaultToVaultGroup,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1268)     help=(
1269)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_EXPORT_01),
1270)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_EXPORT_02),
1271)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_EXPORT_03),
1272)     ),
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1273) )
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

1274) @version_option
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1275) @standard_logging_options
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1276) @click.pass_context
1277) def derivepassphrase_export(ctx: click.Context, /) -> None:
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1278)     """Export a foreign configuration to standard output.
1279) 
1280)     This is a [`click`][CLICK]-powered command-line interface function,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1281)     and not intended for programmatic use.  See the
1282)     derivepassphrase-export(1) manpage for full documentation of the
1283)     interface.  (See also [`click.testing.CliRunner`][] for controlled,
1284)     programmatic invocation.)
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1285) 
Marco Ricci Update all URLs to stable a...

Marco Ricci authored 3 months ago

1286)     [CLICK]: https://pypi.org/package/click/
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1287) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1288)     """
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1289)     deprecation = logging.getLogger(f'{PROG_NAME}.deprecation')
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1290)     if ctx.invoked_subcommand is None:
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1291)         deprecation.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1292)             _msg.TranslatedString(_msg.WarnMsgTemplate.V10_SUBCOMMAND_REQUIRED)
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1293)         )
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1294)         # See definition of click.Group.invoke, non-chained case.
1295)         with ctx:
1296)             sub_ctx = derivepassphrase_export_vault.make_context(
1297)                 'vault', ctx.args, parent=ctx
1298)             )
1299)             # Constructing the subcontext above will usually already
1300)             # lead to a click.UsageError, so this block typically won't
1301)             # actually be called.
1302)             with sub_ctx:  # pragma: no cover
1303)                 return derivepassphrase_export_vault.invoke(sub_ctx)
1304)     return None
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1305) 
1306) 
1307) def _load_data(
1308)     fmt: Literal['v0.2', 'v0.3', 'storeroom'],
1309)     path: str | bytes | os.PathLike[str],
1310)     key: bytes,
1311) ) -> Any:  # noqa: ANN401
1312)     contents: bytes
1313)     module: types.ModuleType
Marco Ricci Add support for Python 3.9

Marco Ricci authored 3 months ago

1314)     # Use match/case here once Python 3.9 becomes unsupported.
1315)     if fmt == 'v0.2':
1316)         module = importlib.import_module(
1317)             'derivepassphrase.exporter.vault_native'
1318)         )
1319)         if module.STUBBED:
1320)             raise ModuleNotFoundError
1321)         with open(path, 'rb') as infile:
1322)             contents = base64.standard_b64decode(infile.read())
1323)         return module.export_vault_native_data(
1324)             contents, key, try_formats=['v0.2']
1325)         )
1326)     elif fmt == 'v0.3':  # noqa: RET505
1327)         module = importlib.import_module(
1328)             'derivepassphrase.exporter.vault_native'
1329)         )
1330)         if module.STUBBED:
1331)             raise ModuleNotFoundError
1332)         with open(path, 'rb') as infile:
1333)             contents = base64.standard_b64decode(infile.read())
1334)         return module.export_vault_native_data(
1335)             contents, key, try_formats=['v0.3']
1336)         )
1337)     elif fmt == 'storeroom':
1338)         module = importlib.import_module('derivepassphrase.exporter.storeroom')
1339)         if module.STUBBED:
1340)             raise ModuleNotFoundError
1341)         return module.export_storeroom_data(path, key)
1342)     else:  # pragma: no cover
1343)         assert_never(fmt)
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1344) 
1345) 
Marco Ricci Add shell completion suppor...

Marco Ricci authored 1 week ago

1346) def _shell_complete_vault_path(  # pragma: no cover
1347)     ctx: click.Context,
1348)     param: click.Parameter,
1349)     incomplete: str,
1350) ) -> list[str | click.shell_completion.CompletionItem]:
1351)     del ctx, param
1352)     if incomplete and 'VAULT_PATH'.startswith(incomplete):
1353)         ret: set[str | click.shell_completion.CompletionItem] = {'VAULT_PATH'}
1354)         for f in os.listdir():
1355)             if f.startswith(incomplete):
1356)                 ret.add(f + os.path.sep if os.path.isdir(f) else f)
1357)         return sorted(ret)
1358)     return [
1359)         click.shell_completion.CompletionItem('', type='file'),
1360)     ]
1361) 
1362) 
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1363) @derivepassphrase_export.command(
1364)     'vault',
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1365)     context_settings={'help_option_names': ['-h', '--help']},
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1366)     cls=CommandWithHelpGroups,
1367)     help=(
1368)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_EXPORT_VAULT_01),
1369)         _msg.TranslatedString(
1370)             _msg.Label.DERIVEPASSPHRASE_EXPORT_VAULT_02,
1371)             path_metavar=_msg.TranslatedString(
1372)                 _msg.Label.EXPORT_VAULT_METAVAR_PATH,
1373)             ),
1374)         ),
1375)         _msg.TranslatedString(
1376)             _msg.Label.DERIVEPASSPHRASE_EXPORT_VAULT_03,
1377)             path_metavar=_msg.TranslatedString(
1378)                 _msg.Label.EXPORT_VAULT_METAVAR_PATH,
1379)             ),
1380)         ),
1381)     ),
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1382) )
1383) @click.option(
1384)     '-f',
1385)     '--format',
1386)     'formats',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1387)     metavar=_msg.TranslatedString(_msg.Label.EXPORT_VAULT_FORMAT_METAVAR_FMT),
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1388)     multiple=True,
1389)     default=('v0.3', 'v0.2', 'storeroom'),
1390)     type=click.Choice(['v0.2', 'v0.3', 'storeroom']),
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1391)     help=_msg.TranslatedString(
1392)         _msg.Label.EXPORT_VAULT_FORMAT_HELP_TEXT,
1393)         defaults_hint=_msg.TranslatedString(
1394)             _msg.Label.EXPORT_VAULT_FORMAT_DEFAULTS_HELP_TEXT,
1395)         ),
1396)         metavar=_msg.TranslatedString(
1397)             _msg.Label.EXPORT_VAULT_FORMAT_METAVAR_FMT,
1398)         ),
1399)     ),
1400)     cls=StandardOption,
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1401) )
1402) @click.option(
1403)     '-k',
1404)     '--key',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1405)     metavar=_msg.TranslatedString(_msg.Label.EXPORT_VAULT_KEY_METAVAR_K),
1406)     help=_msg.TranslatedString(
1407)         _msg.Label.EXPORT_VAULT_KEY_HELP_TEXT,
1408)         metavar=_msg.TranslatedString(_msg.Label.EXPORT_VAULT_KEY_METAVAR_K),
1409)         defaults_hint=_msg.TranslatedString(
1410)             _msg.Label.EXPORT_VAULT_KEY_DEFAULTS_HELP_TEXT,
1411)         ),
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1412)     ),
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1413)     cls=StandardOption,
1414) )
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

1415) @version_option
1416) @standard_logging_options
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1417) @click.argument(
1418)     'path',
1419)     metavar=_msg.TranslatedString(_msg.Label.EXPORT_VAULT_METAVAR_PATH),
1420)     required=True,
Marco Ricci Add shell completion suppor...

Marco Ricci authored 1 week ago

1421)     shell_complete=_shell_complete_vault_path,
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1422) )
1423) @click.pass_context
1424) def derivepassphrase_export_vault(
1425)     ctx: click.Context,
1426)     /,
1427)     *,
1428)     path: str | bytes | os.PathLike[str],
1429)     formats: Sequence[Literal['v0.2', 'v0.3', 'storeroom']] = (),
1430)     key: str | bytes | None = None,
1431) ) -> None:
1432)     """Export a vault-native configuration to standard output.
1433) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1434)     This is a [`click`][CLICK]-powered command-line interface function,
1435)     and not intended for programmatic use.  See the
1436)     derivepassphrase-export-vault(1) manpage for full documentation of
1437)     the interface.  (See also [`click.testing.CliRunner`][] for
1438)     controlled, programmatic invocation.)
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1439) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1440)     [CLICK]: https://pypi.org/package/click/
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1441) 
1442)     """
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1443)     logger = logging.getLogger(PROG_NAME)
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1444)     if path in {'VAULT_PATH', b'VAULT_PATH'}:
1445)         path = exporter.get_vault_path()
1446)     if key is None:
1447)         key = exporter.get_vault_key()
1448)     elif isinstance(key, str):  # pragma: no branch
1449)         key = key.encode('utf-8')
1450)     for fmt in formats:
1451)         try:
1452)             config = _load_data(fmt, path, key)
1453)         except (
1454)             IsADirectoryError,
1455)             NotADirectoryError,
1456)             ValueError,
1457)             RuntimeError,
1458)         ):
Marco Ricci Replace strings in `derivep...

Marco Ricci authored 1 week ago

1459)             logger.info(
1460)                 _msg.TranslatedString(
1461)                     _msg.InfoMsgTemplate.CANNOT_LOAD_AS_VAULT_CONFIG,
1462)                     path=path,
1463)                     fmt=fmt,
1464)                 ),
1465)             )
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1466)             continue
1467)         except OSError as exc:
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1468)             logger.error(
Marco Ricci Replace strings in `derivep...

Marco Ricci authored 1 week ago

1469)                 _msg.TranslatedString(
1470)                     _msg.ErrMsgTemplate.CANNOT_PARSE_AS_VAULT_CONFIG_OSERROR,
1471)                     path=path,
1472)                     error=exc.strerror,
1473)                     filename=exc.filename,
1474)                 ).maybe_without_filename(),
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1475)             )
1476)             ctx.exit(1)
1477)         except ModuleNotFoundError:
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1478)             logger.error(
Marco Ricci Replace strings in `derivep...

Marco Ricci authored 1 week ago

1479)                 _msg.TranslatedString(
1480)                     _msg.ErrMsgTemplate.MISSING_MODULE,
1481)                     module='cryptography',
1482)                 ),
1483)             )
1484)             logger.info(
1485)                 _msg.TranslatedString(
1486)                     _msg.InfoMsgTemplate.PIP_INSTALL_EXTRA,
1487)                     extra_name='export',
1488)                 ),
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1489)             )
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1490)             ctx.exit(1)
1491)         else:
1492)             if not _types.is_vault_config(config):
Marco Ricci Replace strings in `derivep...

Marco Ricci authored 1 week ago

1493)                 logger.error(
1494)                     _msg.TranslatedString(
1495)                         _msg.ErrMsgTemplate.INVALID_VAULT_CONFIG,
1496)                         config=config,
1497)                     ),
1498)                 )
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1499)                 ctx.exit(1)
1500)             click.echo(json.dumps(config, indent=2, sort_keys=True))
1501)             break
1502)     else:
Marco Ricci Replace strings in `derivep...

Marco Ricci authored 1 week ago

1503)         logger.error(
1504)             _msg.TranslatedString(
1505)                 _msg.ErrMsgTemplate.CANNOT_PARSE_AS_VAULT_CONFIG,
1506)                 path=path,
1507)             ).maybe_without_filename(),
1508)         )
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1509)         ctx.exit(1)
1510) 
1511) 
1512) # Vault
1513) # =====
1514) 
1515) 
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

1516) def _config_filename(
Marco Ricci Make obtaining the compatib...

Marco Ricci authored 3 weeks ago

1517)     subsystem: str | None = 'old settings.json',
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

1518) ) -> str | bytes | pathlib.Path:
1519)     """Return the filename of the configuration file for the subsystem.
1520) 
1521)     The (implicit default) file is currently named `settings.json`,
1522)     located within the configuration directory as determined by the
1523)     `DERIVEPASSPHRASE_PATH` environment variable, or by
1524)     [`click.get_app_dir`][] in POSIX mode.  Depending on the requested
1525)     subsystem, this will usually be a different file within that
1526)     directory.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

1527) 
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

1528)     Args:
1529)         subsystem:
1530)             Name of the configuration subsystem whose configuration
1531)             filename to return.  If not given, return the old filename
1532)             from before the subcommand migration.  If `None`, return the
1533)             configuration directory instead.
1534) 
1535)     Raises:
1536)         AssertionError:
1537)             An unknown subsystem was passed.
1538) 
1539)     Deprecated:
1540)         Since v0.2.0: The implicit default subsystem and the old
1541)         configuration filename are deprecated, and will be removed in v1.0.
1542)         The subsystem will be mandatory to specify.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

1543) 
1544)     """
1545)     path: str | bytes | pathlib.Path
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

1546)     path = os.getenv(PROG_NAME.upper() + '_PATH') or click.get_app_dir(
1547)         PROG_NAME, force_posix=True
1548)     )
Marco Ricci Add support for Python 3.9

Marco Ricci authored 3 months ago

1549)     # Use match/case here once Python 3.9 becomes unsupported.
1550)     if subsystem is None:
1551)         return path
Marco Ricci Make obtaining the compatib...

Marco Ricci authored 3 weeks ago

1552)     elif subsystem == 'vault':  # noqa: RET505
Marco Ricci Add support for Python 3.9

Marco Ricci authored 3 months ago

1553)         filename = f'{subsystem}.json'
Marco Ricci Introduce a central user co...

Marco Ricci authored 3 weeks ago

1554)     elif subsystem == 'user configuration':
1555)         filename = 'config.toml'
Marco Ricci Make obtaining the compatib...

Marco Ricci authored 3 weeks ago

1556)     elif subsystem == 'old settings.json':
1557)         filename = 'settings.json'
Marco Ricci Add support for Python 3.9

Marco Ricci authored 3 months ago

1558)     else:  # pragma: no cover
1559)         msg = f'Unknown configuration subsystem: {subsystem!r}'
1560)         raise AssertionError(msg)
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

1561)     return os.path.join(path, filename)
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

1562) 
1563) 
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 5 months ago

1564) def _load_config() -> _types.VaultConfig:
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

1565)     """Load a vault(1)-compatible config from the application directory.
1566) 
Marco Ricci Generate nicer documentatio...

Marco Ricci authored 3 months ago

1567)     The filename is obtained via [`_config_filename`][].  This must be
1568)     an unencrypted JSON file.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

1569) 
1570)     Returns:
Marco Ricci Generate nicer documentatio...

Marco Ricci authored 3 months ago

1571)         The vault settings.  See [`_types.VaultConfig`][] for details.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

1572) 
1573)     Raises:
1574)         OSError:
1575)             There was an OS error accessing the file.
1576)         ValueError:
1577)             The data loaded from the file is not a vault(1)-compatible
1578)             config.
1579) 
1580)     """
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

1581)     filename = _config_filename(subsystem='vault')
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

1582)     with open(filename, 'rb') as fileobj:
1583)         data = json.load(fileobj)
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 5 months ago

1584)     if not _types.is_vault_config(data):
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

1585)         raise ValueError(_INVALID_VAULT_CONFIG)
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

1586)     return data
1587) 
1588) 
Marco Ricci Permit one flaky test and f...

Marco Ricci authored 3 months ago

1589) def _migrate_and_load_old_config() -> tuple[
1590)     _types.VaultConfig, OSError | None
1591) ]:
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

1592)     """Load and migrate a vault(1)-compatible config.
1593) 
Marco Ricci Generate nicer documentatio...

Marco Ricci authored 3 months ago

1594)     The (old) filename is obtained via [`_config_filename`][].  This
1595)     must be an unencrypted JSON file.  After loading, the file is
1596)     migrated to the new standard filename.
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

1597) 
1598)     Returns:
1599)         The vault settings, and an optional exception encountered during
Marco Ricci Generate nicer documentatio...

Marco Ricci authored 3 months ago

1600)         migration.  See [`_types.VaultConfig`][] for details on the
1601)         former.
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

1602) 
1603)     Raises:
1604)         OSError:
1605)             There was an OS error accessing the old file.
1606)         ValueError:
1607)             The data loaded from the file is not a vault(1)-compatible
1608)             config.
1609) 
1610)     """
1611)     new_filename = _config_filename(subsystem='vault')
Marco Ricci Make obtaining the compatib...

Marco Ricci authored 3 weeks ago

1612)     old_filename = _config_filename(subsystem='old settings.json')
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

1613)     with open(old_filename, 'rb') as fileobj:
1614)         data = json.load(fileobj)
1615)     if not _types.is_vault_config(data):
1616)         raise ValueError(_INVALID_VAULT_CONFIG)
1617)     try:
1618)         os.replace(old_filename, new_filename)
1619)     except OSError as exc:
1620)         return data, exc
1621)     else:
1622)         return data, None
1623) 
1624) 
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 5 months ago

1625) def _save_config(config: _types.VaultConfig, /) -> None:
Marco Ricci Create the configuration di...

Marco Ricci authored 5 months ago

1626)     """Save a vault(1)-compatible config to the application directory.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

1627) 
Marco Ricci Generate nicer documentatio...

Marco Ricci authored 3 months ago

1628)     The filename is obtained via [`_config_filename`][].  The config
1629)     will be stored as an unencrypted JSON file.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

1630) 
1631)     Args:
1632)         config:
1633)             vault configuration to save.
1634) 
1635)     Raises:
1636)         OSError:
1637)             There was an OS error accessing or writing the file.
1638)         ValueError:
1639)             The data cannot be stored as a vault(1)-compatible config.
1640) 
1641)     """
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 5 months ago

1642)     if not _types.is_vault_config(config):
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

1643)         raise ValueError(_INVALID_VAULT_CONFIG)
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

1644)     filename = _config_filename(subsystem='vault')
Marco Ricci Create the configuration di...

Marco Ricci authored 5 months ago

1645)     filedir = os.path.dirname(os.path.abspath(filename))
1646)     try:
1647)         os.makedirs(filedir, exist_ok=False)
1648)     except FileExistsError:
1649)         if not os.path.isdir(filedir):
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

1650)             raise  # noqa: DOC501
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

1651)     with open(filename, 'w', encoding='UTF-8') as fileobj:
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

1652)         json.dump(config, fileobj)
1653) 
1654) 
Marco Ricci Introduce a central user co...

Marco Ricci authored 3 weeks ago

1655) def _load_user_config() -> dict[str, Any]:
1656)     """Load the user config from the application directory.
1657) 
1658)     The filename is obtained via [`_config_filename`][].
1659) 
1660)     Returns:
1661)         The user configuration, as a nested `dict`.
1662) 
1663)     Raises:
1664)         OSError:
1665)             There was an OS error accessing the file.
1666)         ValueError:
1667)             The data loaded from the file is not a valid configuration
1668)             file.
1669) 
1670)     """
1671)     filename = _config_filename(subsystem='user configuration')
1672)     with open(filename, 'rb') as fileobj:
1673)         return tomllib.load(fileobj)
1674) 
1675) 
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1676) def _get_suitable_ssh_keys(
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 5 months ago

1677)     conn: ssh_agent.SSHAgentClient | socket.socket | None = None, /
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 5 months ago

1678) ) -> Iterator[_types.KeyCommentPair]:
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1679)     """Yield all SSH keys suitable for passphrase derivation.
1680) 
1681)     Suitable SSH keys are queried from the running SSH agent (see
Marco Ricci Generate nicer documentatio...

Marco Ricci authored 3 months ago

1682)     [`ssh_agent.SSHAgentClient.list_keys`][]).
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1683) 
1684)     Args:
1685)         conn:
Marco Ricci Support one-off SSH agent c...

Marco Ricci authored 1 month ago

1686)             An optional connection hint to the SSH agent.  See
1687)             [`ssh_agent.SSHAgentClient.ensure_agent_subcontext`][].
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1688) 
1689)     Yields:
Marco Ricci Convert old syntax for Yiel...

Marco Ricci authored 3 months ago

1690)         Every SSH key from the SSH agent that is suitable for passphrase
1691)         derivation.
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1692) 
1693)     Raises:
Marco Ricci Document and handle other e...

Marco Ricci authored 4 months ago

1694)         KeyError:
1695)             `conn` was `None`, and the `SSH_AUTH_SOCK` environment
1696)             variable was not found.
Marco Ricci Fail gracefully if UNIX dom...

Marco Ricci authored 3 months ago

1697)         NotImplementedError:
1698)             `conn` was `None`, and this Python does not support
1699)             [`socket.AF_UNIX`][], so the SSH agent client cannot be
1700)             automatically set up.
Marco Ricci Document and handle other e...

Marco Ricci authored 4 months ago

1701)         OSError:
1702)             `conn` was a socket or `None`, and there was an error
1703)             setting up a socket connection to the agent.
Marco Ricci Distinguish between a key l...

Marco Ricci authored 6 months ago

1704)         LookupError:
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1705)             No keys usable for passphrase derivation are loaded into the
1706)             SSH agent.
Marco Ricci Distinguish between a key l...

Marco Ricci authored 6 months ago

1707)         RuntimeError:
1708)             There was an error communicating with the SSH agent.
Marco Ricci Fix miscellaneous small doc...

Marco Ricci authored 3 months ago

1709)         ssh_agent.SSHAgentFailedError:
Marco Ricci Add a specific error class...

Marco Ricci authored 4 months ago

1710)             The agent failed to supply a list of loaded keys.
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1711) 
1712)     """
Marco Ricci Support one-off SSH agent c...

Marco Ricci authored 1 month ago

1713)     with ssh_agent.SSHAgentClient.ensure_agent_subcontext(conn) as client:
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1714)         try:
1715)             all_key_comment_pairs = list(client.list_keys())
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

1716)         except EOFError as exc:  # pragma: no cover
1717)             raise RuntimeError(_AGENT_COMMUNICATION_ERROR) from exc
Marco Ricci Publish polished `is_suitab...

Marco Ricci authored 1 month ago

1718)         suitable_keys = copy.copy(all_key_comment_pairs)
1719)         for pair in all_key_comment_pairs:
1720)             key, _comment = pair
1721)             if vault.Vault.is_suitable_ssh_key(key, client=client):
1722)                 yield pair
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1723)     if not suitable_keys:  # pragma: no cover
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1724)         raise LookupError(_NO_SUITABLE_KEYS)
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1725) 
1726) 
1727) def _prompt_for_selection(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

1728)     items: Sequence[str | bytes],
1729)     heading: str = 'Possible choices:',
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1730)     single_choice_prompt: str = 'Confirm this choice?',
1731) ) -> int:
1732)     """Prompt user for a choice among the given items.
1733) 
1734)     Print the heading, if any, then present the items to the user.  If
1735)     there are multiple items, prompt the user for a selection, validate
1736)     the choice, then return the list index of the selected item.  If
1737)     there is only a single item, request confirmation for that item
1738)     instead, and return the correct index.
1739) 
1740)     Args:
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

1741)         items:
1742)             The list of items to choose from.
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1743)         heading:
1744)             A heading for the list of items, to print immediately
1745)             before.  Defaults to a reasonable standard heading.  If
1746)             explicitly empty, print no heading.
1747)         single_choice_prompt:
1748)             The confirmation prompt if there is only a single possible
1749)             choice.  Defaults to a reasonable standard prompt.
1750) 
1751)     Returns:
1752)         An index into the items sequence, indicating the user's
1753)         selection.
1754) 
1755)     Raises:
1756)         IndexError:
1757)             The user made an invalid or empty selection, or requested an
1758)             abort.
1759) 
1760)     """
1761)     n = len(items)
1762)     if heading:
1763)         click.echo(click.style(heading, bold=True))
1764)     for i, x in enumerate(items, start=1):
1765)         click.echo(click.style(f'[{i}]', bold=True), nl=False)
1766)         click.echo(' ', nl=False)
1767)         click.echo(x)
1768)     if n > 1:
1769)         choices = click.Choice([''] + [str(i) for i in range(1, n + 1)])
1770)         choice = click.prompt(
1771)             f'Your selection? (1-{n}, leave empty to abort)',
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

1772)             err=True,
1773)             type=choices,
1774)             show_choices=False,
1775)             show_default=False,
1776)             default='',
1777)         )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1778)         if not choice:
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

1779)             raise IndexError(_EMPTY_SELECTION)
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1780)         return int(choice) - 1
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

1781)     prompt_suffix = (
1782)         ' ' if single_choice_prompt.endswith(tuple('?.!')) else ': '
1783)     )
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

1784)     try:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

1785)         click.confirm(
1786)             single_choice_prompt,
1787)             prompt_suffix=prompt_suffix,
1788)             err=True,
1789)             abort=True,
1790)             default=False,
1791)             show_default=False,
1792)         )
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

1793)     except click.Abort:
1794)         raise IndexError(_EMPTY_SELECTION) from None
1795)     return 0
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1796) 
1797) 
1798) def _select_ssh_key(
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 5 months ago

1799)     conn: ssh_agent.SSHAgentClient | socket.socket | None = None, /
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1800) ) -> bytes | bytearray:
1801)     """Interactively select an SSH key for passphrase derivation.
1802) 
1803)     Suitable SSH keys are queried from the running SSH agent (see
Marco Ricci Generate nicer documentatio...

Marco Ricci authored 3 months ago

1804)     [`ssh_agent.SSHAgentClient.list_keys`][]), then the user is prompted
1805)     interactively (see [`click.prompt`][]) for a selection.
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1806) 
1807)     Args:
1808)         conn:
Marco Ricci Support one-off SSH agent c...

Marco Ricci authored 1 month ago

1809)             An optional connection hint to the SSH agent.  See
1810)             [`ssh_agent.SSHAgentClient.ensure_agent_subcontext`][].
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1811) 
1812)     Returns:
1813)         The selected SSH key.
1814) 
1815)     Raises:
Marco Ricci Document and handle other e...

Marco Ricci authored 4 months ago

1816)         KeyError:
1817)             `conn` was `None`, and the `SSH_AUTH_SOCK` environment
1818)             variable was not found.
Marco Ricci Fail gracefully if UNIX dom...

Marco Ricci authored 3 months ago

1819)         NotImplementedError:
1820)             `conn` was `None`, and this Python does not support
1821)             [`socket.AF_UNIX`][], so the SSH agent client cannot be
1822)             automatically set up.
Marco Ricci Document and handle other e...

Marco Ricci authored 4 months ago

1823)         OSError:
1824)             `conn` was a socket or `None`, and there was an error
1825)             setting up a socket connection to the agent.
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1826)         IndexError:
1827)             The user made an invalid or empty selection, or requested an
1828)             abort.
Marco Ricci Distinguish between a key l...

Marco Ricci authored 6 months ago

1829)         LookupError:
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1830)             No keys usable for passphrase derivation are loaded into the
1831)             SSH agent.
Marco Ricci Distinguish between a key l...

Marco Ricci authored 6 months ago

1832)         RuntimeError:
1833)             There was an error communicating with the SSH agent.
Marco Ricci Add a specific error class...

Marco Ricci authored 4 months ago

1834)         SSHAgentFailedError:
1835)             The agent failed to supply a list of loaded keys.
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1836)     """
1837)     suitable_keys = list(_get_suitable_ssh_keys(conn))
1838)     key_listing: list[str] = []
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 5 months ago

1839)     unstring_prefix = ssh_agent.SSHAgentClient.unstring_prefix
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1840)     for key, comment in suitable_keys:
1841)         keytype = unstring_prefix(key)[0].decode('ASCII')
1842)         key_str = base64.standard_b64encode(key).decode('ASCII')
Marco Ricci Make suitable SSH key listi...

Marco Ricci authored 1 month ago

1843)         remaining_key_display_length = KEY_DISPLAY_LENGTH - 1 - len(keytype)
1844)         key_extract = min(
1845)             key_str,
1846)             '...' + key_str[-remaining_key_display_length:],
1847)             key=len,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

1848)         )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1849)         comment_str = comment.decode('UTF-8', errors='replace')
Marco Ricci Make suitable SSH key listi...

Marco Ricci authored 1 month ago

1850)         key_listing.append(f'{keytype} {key_extract}  {comment_str}')
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1851)     choice = _prompt_for_selection(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

1852)         key_listing,
1853)         heading='Suitable SSH keys:',
1854)         single_choice_prompt='Use this key?',
1855)     )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1856)     return suitable_keys[choice].key
1857) 
1858) 
1859) def _prompt_for_passphrase() -> str:
1860)     """Interactively prompt for the passphrase.
1861) 
1862)     Calls [`click.prompt`][] internally.  Moved into a separate function
1863)     mainly for testing/mocking purposes.
1864) 
1865)     Returns:
1866)         The user input.
1867) 
1868)     """
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 5 months ago

1869)     return cast(
1870)         str,
1871)         click.prompt(
1872)             'Passphrase',
1873)             default='',
1874)             hide_input=True,
1875)             show_default=False,
1876)             err=True,
1877)         ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

1878)     )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1879) 
1880) 
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

1881) def _toml_key(*parts: str) -> str:
1882)     """Return a formatted TOML key, given its parts."""
Marco Ricci Fix formatting, some covera...

Marco Ricci authored 2 weeks ago

1883) 
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

1884)     def escape(string: str) -> str:
1885)         translated = string.translate({
1886)             0: r'\u0000',
1887)             1: r'\u0001',
1888)             2: r'\u0002',
1889)             3: r'\u0003',
1890)             4: r'\u0004',
1891)             5: r'\u0005',
1892)             6: r'\u0006',
1893)             7: r'\u0007',
1894)             8: r'\b',
1895)             9: r'\t',
1896)             10: r'\n',
1897)             11: r'\u000B',
1898)             12: r'\f',
1899)             13: r'\r',
1900)             14: r'\u000E',
1901)             15: r'\u000F',
1902)             ord('"'): r'\"',
1903)             ord('\\'): r'\\',
1904)             127: r'\u007F',
1905)         })
1906)         return f'"{translated}"' if translated != string else string
Marco Ricci Fix formatting, some covera...

Marco Ricci authored 2 weeks ago

1907) 
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

1908)     return '.'.join(map(escape, parts))
1909) 
1910) 
Marco Ricci Signal and list falsy value...

Marco Ricci authored 3 months ago

1911) class _ORIGIN(enum.Enum):
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

1912)     INTERACTIVE: str = 'interactive input'
Marco Ricci Signal and list falsy value...

Marco Ricci authored 3 months ago

1913) 
1914) 
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

1915) def _check_for_misleading_passphrase(
Marco Ricci Signal and list falsy value...

Marco Ricci authored 3 months ago

1916)     key: tuple[str, ...] | _ORIGIN,
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

1917)     value: dict[str, Any],
1918)     *,
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

1919)     main_config: dict[str, Any],
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

1920) ) -> None:
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

1921)     form_key = 'unicode-normalization-form'
1922)     default_form: str = main_config.get('vault', {}).get(
1923)         f'default-{form_key}', 'NFC'
1924)     )
1925)     form_dict: dict[str, dict] = main_config.get('vault', {}).get(form_key, {})
1926)     form: Any = (
1927)         default_form
1928)         if isinstance(key, _ORIGIN) or key == ('global',)
1929)         else form_dict.get(key[1], default_form)
1930)     )
1931)     config_key = (
1932)         _toml_key('vault', key[1], form_key)
1933)         if isinstance(key, tuple) and len(key) > 1 and key[1] in form_dict
1934)         else f'vault.default-{form_key}'
1935)     )
1936)     if form not in {'NFC', 'NFD', 'NFKC', 'NFKD'}:
1937)         msg = f'Invalid value {form!r} for config key {config_key}'
1938)         raise AssertionError(msg)
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1939)     logger = logging.getLogger(PROG_NAME)
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

1940)     formatted_key = (
1941)         key.value if isinstance(key, _ORIGIN) else _types.json_path(key)
1942)     )
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

1943)     if 'phrase' in value:
1944)         phrase = value['phrase']
1945)         if not unicodedata.is_normalized(form, phrase):
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1946)             logger.warning(
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

1947)                 (
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1948)                     'The %s passphrase is not %s-normalized.  Its '
1949)                     'serialization as a byte string may not be what you '
1950)                     'expect it to be, even if it *displays* correctly.  '
1951)                     'Please make sure to double-check any derived '
1952)                     'passphrases for unexpected results.'
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

1953)                 ),
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1954)                 formatted_key,
1955)                 form,
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

1956)                 stacklevel=2,
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

1957)             )
1958) 
1959) 
Marco Ricci Hoist and add tests for int...

Marco Ricci authored 3 weeks ago

1960) def _key_to_phrase(
1961)     key_: str | bytes | bytearray,
1962)     /,
1963)     *,
1964)     error_callback: Callable[..., NoReturn] = sys.exit,
1965) ) -> bytes | bytearray:
1966)     key = base64.standard_b64decode(key_)
1967)     try:
1968)         with ssh_agent.SSHAgentClient.ensure_agent_subcontext() as client:
1969)             try:
1970)                 return vault.Vault.phrase_from_key(key, conn=client)
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

1971)             except ssh_agent.SSHAgentFailedError as exc:
Marco Ricci Hoist and add tests for int...

Marco Ricci authored 3 weeks ago

1972)                 try:
1973)                     keylist = client.list_keys()
1974)                 except ssh_agent.SSHAgentFailedError:
1975)                     pass
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

1976)                 except Exception as exc2:  # noqa: BLE001
1977)                     exc.__context__ = exc2
Marco Ricci Hoist and add tests for int...

Marco Ricci authored 3 weeks ago

1978)                 else:
1979)                     if not any(  # pragma: no branch
1980)                         k == key for k, _ in keylist
1981)                     ):
1982)                         error_callback(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1983)                             _msg.TranslatedString(
1984)                                 _msg.ErrMsgTemplate.SSH_KEY_NOT_LOADED
1985)                             )
Marco Ricci Hoist and add tests for int...

Marco Ricci authored 3 weeks ago

1986)                         )
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1987)                 error_callback(
1988)                     _msg.TranslatedString(
1989)                         _msg.ErrMsgTemplate.AGENT_REFUSED_SIGNATURE
1990)                     ),
1991)                     exc_info=exc,
1992)                 )
Marco Ricci Hoist and add tests for int...

Marco Ricci authored 3 weeks ago

1993)     except KeyError:
1994)         error_callback(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1995)             _msg.TranslatedString(_msg.ErrMsgTemplate.NO_SSH_AGENT_FOUND)
Marco Ricci Hoist and add tests for int...

Marco Ricci authored 3 weeks ago

1996)         )
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1997)     except NotImplementedError:
1998)         error_callback(_msg.TranslatedString(_msg.ErrMsgTemplate.NO_AF_UNIX))
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

1999)     except OSError as exc:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2000)         error_callback(
2001)             _msg.TranslatedString(
2002)                 _msg.ErrMsgTemplate.CANNOT_CONNECT_TO_AGENT,
2003)                 error=exc.strerror,
2004)                 filename=exc.filename,
2005)             ).maybe_without_filename()
2006)         )
2007)     except RuntimeError as exc:
2008)         error_callback(
2009)             _msg.TranslatedString(_msg.ErrMsgTemplate.CANNOT_UNDERSTAND_AGENT),
2010)             exc_info=exc,
2011)         )
Marco Ricci Hoist and add tests for int...

Marco Ricci authored 3 weeks ago

2012) 
2013) 
Marco Ricci Support exporting the `vaul...

Marco Ricci authored 2 weeks ago

2014) def _print_config_as_sh_script(
2015)     config: _types.VaultConfig,
2016)     /,
2017)     *,
2018)     outfile: TextIO,
2019)     prog_name_list: Sequence[str],
2020) ) -> None:
2021)     service_keys = (
2022)         'length',
2023)         'repeat',
2024)         'lower',
2025)         'upper',
2026)         'number',
2027)         'space',
2028)         'dash',
2029)         'symbol',
2030)     )
2031)     print('#!/bin/sh -e', file=outfile)
2032)     print(file=outfile)
2033)     print(shlex.join([*prog_name_list, '--clear']), file=outfile)
2034)     sv_obj_pairs: list[
2035)         tuple[
2036)             str | None,
2037)             _types.VaultConfigGlobalSettings
2038)             | _types.VaultConfigServicesSettings,
2039)         ],
2040)     ] = list(config['services'].items())
2041)     if config.get('global', {}):
2042)         sv_obj_pairs.insert(0, (None, config['global']))
2043)     for sv, sv_obj in sv_obj_pairs:
2044)         this_service_keys = tuple(k for k in service_keys if k in sv_obj)
2045)         this_other_keys = tuple(k for k in sv_obj if k not in service_keys)
2046)         if this_other_keys:
2047)             other_sv_obj = {k: sv_obj[k] for k in this_other_keys}  # type: ignore[literal-required]
2048)             dumped_config = json.dumps(
2049)                 (
2050)                     {'services': {sv: other_sv_obj}}
2051)                     if sv is not None
2052)                     else {'global': other_sv_obj, 'services': {}}
2053)                 ),
2054)                 ensure_ascii=False,
2055)                 indent=None,
2056)             )
2057)             print(
2058)                 shlex.join([*prog_name_list, '--import', '-']) + " <<'HERE'",
2059)                 dumped_config,
2060)                 'HERE',
2061)                 sep='\n',
2062)                 file=outfile,
2063)             )
2064)         if not this_service_keys and not this_other_keys and sv:
2065)             dumped_config = json.dumps(
2066)                 {'services': {sv: {}}},
2067)                 ensure_ascii=False,
2068)                 indent=None,
2069)             )
2070)             print(
2071)                 shlex.join([*prog_name_list, '--import', '-']) + " <<'HERE'",
2072)                 dumped_config,
2073)                 'HERE',
2074)                 sep='\n',
2075)                 file=outfile,
2076)             )
2077)         elif this_service_keys:
2078)             tokens = [*prog_name_list, '--config']
2079)             for key in this_service_keys:
2080)                 tokens.extend([f'--{key}', str(sv_obj[key])])  # type: ignore[literal-required]
2081)             if sv is not None:
2082)                 tokens.extend(['--', sv])
2083)             print(shlex.join(tokens), file=outfile)
2084) 
2085) 
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2086) # Concrete option groups used by this command-line interface.
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

2087) class PassphraseGenerationOption(OptionGroupOption):
2088)     """Passphrase generation options for the CLI."""
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2089) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2090)     option_group_name = _msg.TranslatedString(
2091)         _msg.Label.PASSPHRASE_GENERATION_LABEL
2092)     )
2093)     epilog = _msg.TranslatedString(
2094)         _msg.Label.PASSPHRASE_GENERATION_EPILOG,
2095)         metavar=_msg.TranslatedString(
2096)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2097)         ),
2098)     )
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2099) 
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2100) 
2101) class ConfigurationOption(OptionGroupOption):
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2102)     """Configuration options for the CLI."""
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2103) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2104)     option_group_name = _msg.TranslatedString(_msg.Label.CONFIGURATION_LABEL)
2105)     epilog = _msg.TranslatedString(_msg.Label.CONFIGURATION_EPILOG)
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2106) 
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2107) 
2108) class StorageManagementOption(OptionGroupOption):
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2109)     """Storage management options for the CLI."""
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2110) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2111)     option_group_name = _msg.TranslatedString(
2112)         _msg.Label.STORAGE_MANAGEMENT_LABEL
2113)     )
2114)     epilog = _msg.TranslatedString(
2115)         _msg.Label.STORAGE_MANAGEMENT_EPILOG,
2116)         metavar=_msg.TranslatedString(
2117)             _msg.Label.STORAGE_MANAGEMENT_METAVAR_PATH
2118)         ),
2119)     )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2120) 
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2121) 
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

2122) class CompatibilityOption(OptionGroupOption):
2123)     """Compatibility and incompatibility options for the CLI."""
2124) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2125)     option_group_name = _msg.TranslatedString(
2126)         _msg.Label.COMPATIBILITY_OPTION_LABEL
2127)     )
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

2128) 
2129) 
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2130) def _validate_occurrence_constraint(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2131)     ctx: click.Context,
2132)     param: click.Parameter,
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

2133)     value: Any,  # noqa: ANN401
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2134) ) -> int | None:
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

2135)     """Check that the occurrence constraint is valid (int, 0 or larger).
2136) 
2137)     Args:
2138)         ctx: The `click` context.
2139)         param: The current command-line parameter.
2140)         value: The parameter value to be checked.
2141) 
2142)     Returns:
2143)         The parsed parameter value.
2144) 
2145)     Raises:
2146)         click.BadParameter: The parameter value is invalid.
2147) 
2148)     """
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2149)     del ctx  # Unused.
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

2150)     del param  # Unused.
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2151)     if value is None:
2152)         return value
2153)     if isinstance(value, int):
2154)         int_value = value
2155)     else:
2156)         try:
2157)             int_value = int(value, 10)
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

2158)         except ValueError as exc:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2159)             raise click.BadParameter(_NOT_AN_INTEGER) from exc
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2160)     if int_value < 0:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2161)         raise click.BadParameter(_NOT_A_NONNEGATIVE_INTEGER)
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2162)     return int_value
2163) 
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2164) 
2165) def _validate_length(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2166)     ctx: click.Context,
2167)     param: click.Parameter,
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

2168)     value: Any,  # noqa: ANN401
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2169) ) -> int | None:
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

2170)     """Check that the length is valid (int, 1 or larger).
2171) 
2172)     Args:
2173)         ctx: The `click` context.
2174)         param: The current command-line parameter.
2175)         value: The parameter value to be checked.
2176) 
2177)     Returns:
2178)         The parsed parameter value.
2179) 
2180)     Raises:
2181)         click.BadParameter: The parameter value is invalid.
2182) 
2183)     """
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2184)     del ctx  # Unused.
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

2185)     del param  # Unused.
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2186)     if value is None:
2187)         return value
2188)     if isinstance(value, int):
2189)         int_value = value
2190)     else:
2191)         try:
2192)             int_value = int(value, 10)
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

2193)         except ValueError as exc:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2194)             raise click.BadParameter(_NOT_AN_INTEGER) from exc
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2195)     if int_value < 1:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2196)         raise click.BadParameter(_NOT_A_POSITIVE_INTEGER)
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2197)     return int_value
2198) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2199) 
Marco Ricci Add shell completion suppor...

Marco Ricci authored 1 week ago

2200) def _shell_complete_path(  # pragma: no cover
2201)     ctx: click.Context,
2202)     parameter: click.Parameter,
2203)     incomplete: str,
2204) ) -> list[str | click.shell_completion.CompletionItem]:
2205)     del ctx, parameter, incomplete
2206)     return [click.shell_completion.CompletionItem('', type='file')]
2207) 
2208) 
2209) def _shell_complete_service(  # pragma: no cover
2210)     ctx: click.Context,
2211)     parameter: click.Parameter,
2212)     incomplete: str,
2213) ) -> list[str | click.shell_completion.CompletionItem]:
2214)     del ctx, parameter
2215)     try:
2216)         config = _load_config()
2217)         return [sv for sv in config['services'] if sv.startswith(incomplete)]
2218)     except FileNotFoundError:
2219)         try:
2220)             config, _exc = _migrate_and_load_old_config()
2221)             return [
2222)                 sv for sv in config['services'] if sv.startswith(incomplete)
2223)             ]
2224)         except FileNotFoundError:
2225)             return []
2226)     except Exception:  # noqa: BLE001
2227)         return []
2228) 
2229) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2230) DEFAULT_NOTES_TEMPLATE = """\
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

2231) # Enter notes below the line with the cut mark (ASCII scissors and
2232) # dashes).  Lines above the cut mark (such as this one) will be ignored.
2233) #
2234) # If you wish to clear the notes, leave everything beyond the cut mark
2235) # blank.  However, if you leave the *entire* file blank, also removing
2236) # the cut mark, then the edit is aborted, and the old notes contents are
2237) # retained.
2238) #
2239) # - - - - - >8 - - - - - >8 - - - - - >8 - - - - - >8 - - - - -
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2240) """
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

2241) DEFAULT_NOTES_MARKER = '# - - - - - >8 - - - - -'
2242) 
2243) 
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

2244) @derivepassphrase.command(
2245)     'vault',
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2246)     context_settings={'help_option_names': ['-h', '--help']},
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2247)     cls=CommandWithHelpGroups,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2248)     help=(
2249)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_VAULT_01),
2250)         _msg.TranslatedString(
2251)             _msg.Label.DERIVEPASSPHRASE_VAULT_02,
2252)             service_metavar=_msg.TranslatedString(
2253)                 _msg.Label.VAULT_METAVAR_SERVICE
2254)             ),
2255)         ),
2256)     ),
2257)     epilog=(
2258)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_VAULT_EPILOG_01),
2259)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_VAULT_EPILOG_02),
2260)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2261) )
2262) @click.option(
2263)     '-p',
2264)     '--phrase',
2265)     'use_phrase',
2266)     is_flag=True,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2267)     help=_msg.TranslatedString(
2268)         _msg.Label.DERIVEPASSPHRASE_VAULT_PHRASE_HELP_TEXT
2269)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

2270)     cls=PassphraseGenerationOption,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2271) )
2272) @click.option(
2273)     '-k',
2274)     '--key',
2275)     'use_key',
2276)     is_flag=True,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2277)     help=_msg.TranslatedString(
2278)         _msg.Label.DERIVEPASSPHRASE_VAULT_KEY_HELP_TEXT
2279)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

2280)     cls=PassphraseGenerationOption,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2281) )
2282) @click.option(
2283)     '-l',
2284)     '--length',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2285)     metavar=_msg.TranslatedString(
2286)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2287)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2288)     callback=_validate_length,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2289)     help=_msg.TranslatedString(
2290)         _msg.Label.DERIVEPASSPHRASE_VAULT_LENGTH_HELP_TEXT,
2291)         metavar=_msg.TranslatedString(
2292)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2293)         ),
2294)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

2295)     cls=PassphraseGenerationOption,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2296) )
2297) @click.option(
2298)     '-r',
2299)     '--repeat',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2300)     metavar=_msg.TranslatedString(
2301)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2302)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2303)     callback=_validate_occurrence_constraint,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2304)     help=_msg.TranslatedString(
2305)         _msg.Label.DERIVEPASSPHRASE_VAULT_REPEAT_HELP_TEXT,
2306)         metavar=_msg.TranslatedString(
2307)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2308)         ),
2309)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

2310)     cls=PassphraseGenerationOption,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2311) )
2312) @click.option(
2313)     '--lower',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2314)     metavar=_msg.TranslatedString(
2315)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2316)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2317)     callback=_validate_occurrence_constraint,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2318)     help=_msg.TranslatedString(
2319)         _msg.Label.DERIVEPASSPHRASE_VAULT_LOWER_HELP_TEXT,
2320)         metavar=_msg.TranslatedString(
2321)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2322)         ),
2323)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

2324)     cls=PassphraseGenerationOption,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2325) )
2326) @click.option(
2327)     '--upper',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2328)     metavar=_msg.TranslatedString(
2329)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2330)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2331)     callback=_validate_occurrence_constraint,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2332)     help=_msg.TranslatedString(
2333)         _msg.Label.DERIVEPASSPHRASE_VAULT_UPPER_HELP_TEXT,
2334)         metavar=_msg.TranslatedString(
2335)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2336)         ),
2337)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

2338)     cls=PassphraseGenerationOption,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2339) )
2340) @click.option(
2341)     '--number',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2342)     metavar=_msg.TranslatedString(
2343)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2344)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2345)     callback=_validate_occurrence_constraint,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2346)     help=_msg.TranslatedString(
2347)         _msg.Label.DERIVEPASSPHRASE_VAULT_NUMBER_HELP_TEXT,
2348)         metavar=_msg.TranslatedString(
2349)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2350)         ),
2351)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

2352)     cls=PassphraseGenerationOption,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2353) )
2354) @click.option(
2355)     '--space',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2356)     metavar=_msg.TranslatedString(
2357)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2358)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2359)     callback=_validate_occurrence_constraint,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2360)     help=_msg.TranslatedString(
2361)         _msg.Label.DERIVEPASSPHRASE_VAULT_SPACE_HELP_TEXT,
2362)         metavar=_msg.TranslatedString(
2363)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2364)         ),
2365)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

2366)     cls=PassphraseGenerationOption,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2367) )
2368) @click.option(
2369)     '--dash',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2370)     metavar=_msg.TranslatedString(
2371)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2372)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2373)     callback=_validate_occurrence_constraint,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2374)     help=_msg.TranslatedString(
2375)         _msg.Label.DERIVEPASSPHRASE_VAULT_DASH_HELP_TEXT,
2376)         metavar=_msg.TranslatedString(
2377)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2378)         ),
2379)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

2380)     cls=PassphraseGenerationOption,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2381) )
2382) @click.option(
2383)     '--symbol',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2384)     metavar=_msg.TranslatedString(
2385)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2386)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2387)     callback=_validate_occurrence_constraint,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2388)     help=_msg.TranslatedString(
2389)         _msg.Label.DERIVEPASSPHRASE_VAULT_SYMBOL_HELP_TEXT,
2390)         metavar=_msg.TranslatedString(
2391)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2392)         ),
2393)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

2394)     cls=PassphraseGenerationOption,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2395) )
2396) @click.option(
2397)     '-n',
2398)     '--notes',
2399)     'edit_notes',
2400)     is_flag=True,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2401)     help=_msg.TranslatedString(
2402)         _msg.Label.DERIVEPASSPHRASE_VAULT_NOTES_HELP_TEXT,
2403)         service_metavar=_msg.TranslatedString(
2404)             _msg.Label.VAULT_METAVAR_SERVICE
2405)         ),
2406)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2407)     cls=ConfigurationOption,
2408) )
2409) @click.option(
2410)     '-c',
2411)     '--config',
2412)     'store_config_only',
2413)     is_flag=True,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2414)     help=_msg.TranslatedString(
2415)         _msg.Label.DERIVEPASSPHRASE_VAULT_CONFIG_HELP_TEXT,
2416)         service_metavar=_msg.TranslatedString(
2417)             _msg.Label.VAULT_METAVAR_SERVICE
2418)         ),
2419)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2420)     cls=ConfigurationOption,
2421) )
2422) @click.option(
2423)     '-x',
2424)     '--delete',
2425)     'delete_service_settings',
2426)     is_flag=True,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2427)     help=_msg.TranslatedString(
2428)         _msg.Label.DERIVEPASSPHRASE_VAULT_DELETE_HELP_TEXT,
2429)         service_metavar=_msg.TranslatedString(
2430)             _msg.Label.VAULT_METAVAR_SERVICE
2431)         ),
2432)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2433)     cls=ConfigurationOption,
2434) )
2435) @click.option(
2436)     '--delete-globals',
2437)     is_flag=True,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2438)     help=_msg.TranslatedString(
2439)         _msg.Label.DERIVEPASSPHRASE_VAULT_DELETE_GLOBALS_HELP_TEXT,
2440)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2441)     cls=ConfigurationOption,
2442) )
2443) @click.option(
2444)     '-X',
2445)     '--clear',
2446)     'clear_all_settings',
2447)     is_flag=True,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2448)     help=_msg.TranslatedString(
2449)         _msg.Label.DERIVEPASSPHRASE_VAULT_DELETE_ALL_HELP_TEXT,
2450)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2451)     cls=ConfigurationOption,
2452) )
2453) @click.option(
2454)     '-e',
2455)     '--export',
2456)     'export_settings',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2457)     metavar=_msg.TranslatedString(
2458)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2459)     ),
2460)     help=_msg.TranslatedString(
2461)         _msg.Label.DERIVEPASSPHRASE_VAULT_EXPORT_HELP_TEXT,
2462)         metavar=_msg.TranslatedString(
2463)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2464)         ),
2465)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2466)     cls=StorageManagementOption,
Marco Ricci Add shell completion suppor...

Marco Ricci authored 1 week ago

2467)     shell_complete=_shell_complete_path,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2468) )
2469) @click.option(
2470)     '-i',
2471)     '--import',
2472)     'import_settings',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2473)     metavar=_msg.TranslatedString(
2474)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2475)     ),
2476)     help=_msg.TranslatedString(
2477)         _msg.Label.DERIVEPASSPHRASE_VAULT_IMPORT_HELP_TEXT,
2478)         metavar=_msg.TranslatedString(
2479)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2480)         ),
2481)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2482)     cls=StorageManagementOption,
Marco Ricci Add shell completion suppor...

Marco Ricci authored 1 week ago

2483)     shell_complete=_shell_complete_path,
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2484) )
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

2485) @click.option(
2486)     '--overwrite-existing/--merge-existing',
2487)     'overwrite_config',
2488)     default=False,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2489)     help=_msg.TranslatedString(
2490)         _msg.Label.DERIVEPASSPHRASE_VAULT_OVERWRITE_HELP_TEXT
2491)     ),
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

2492)     cls=CompatibilityOption,
2493) )
Marco Ricci Allow unsetting settings wh...

Marco Ricci authored 2 weeks ago

2494) @click.option(
2495)     '--unset',
2496)     'unset_settings',
2497)     multiple=True,
2498)     type=click.Choice([
2499)         'phrase',
2500)         'key',
2501)         'length',
2502)         'repeat',
2503)         'lower',
2504)         'upper',
2505)         'number',
2506)         'space',
2507)         'dash',
2508)         'symbol',
2509)     ]),
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2510)     help=_msg.TranslatedString(
2511)         _msg.Label.DERIVEPASSPHRASE_VAULT_UNSET_HELP_TEXT
Marco Ricci Allow unsetting settings wh...

Marco Ricci authored 2 weeks ago

2512)     ),
2513)     cls=CompatibilityOption,
2514) )
Marco Ricci Support exporting the `vaul...

Marco Ricci authored 2 weeks ago

2515) @click.option(
2516)     '--export-as',
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

2517)     type=click.Choice(['json', 'sh']),
2518)     default='json',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2519)     help=_msg.TranslatedString(
2520)         _msg.Label.DERIVEPASSPHRASE_VAULT_EXPORT_AS_HELP_TEXT
2521)     ),
Marco Ricci Support exporting the `vaul...

Marco Ricci authored 2 weeks ago

2522)     cls=CompatibilityOption,
2523) )
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

2524) @version_option
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

2525) @standard_logging_options
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2526) @click.argument(
2527)     'service',
2528)     metavar=_msg.TranslatedString(_msg.Label.VAULT_METAVAR_SERVICE),
2529)     required=False,
2530)     default=None,
Marco Ricci Add shell completion suppor...

Marco Ricci authored 1 week ago

2531)     shell_complete=_shell_complete_service,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2532) )
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2533) @click.pass_context
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

2534) def derivepassphrase_vault(  # noqa: C901,PLR0912,PLR0913,PLR0914,PLR0915
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2535)     ctx: click.Context,
2536)     /,
2537)     *,
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2538)     service: str | None = None,
2539)     use_phrase: bool = False,
2540)     use_key: bool = False,
2541)     length: int | None = None,
2542)     repeat: int | None = None,
2543)     lower: int | None = None,
2544)     upper: int | None = None,
2545)     number: int | None = None,
2546)     space: int | None = None,
2547)     dash: int | None = None,
2548)     symbol: int | None = None,
2549)     edit_notes: bool = False,
2550)     store_config_only: bool = False,
2551)     delete_service_settings: bool = False,
2552)     delete_globals: bool = False,
2553)     clear_all_settings: bool = False,
2554)     export_settings: TextIO | pathlib.Path | os.PathLike[str] | None = None,
2555)     import_settings: TextIO | pathlib.Path | os.PathLike[str] | None = None,
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

2556)     overwrite_config: bool = False,
Marco Ricci Allow unsetting settings wh...

Marco Ricci authored 2 weeks ago

2557)     unset_settings: Sequence[str] = (),
Marco Ricci Support exporting the `vaul...

Marco Ricci authored 2 weeks ago

2558)     export_as: Literal['json', 'sh'] = 'json',
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2559) ) -> None:
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

2560)     """Derive a passphrase using the vault(1) derivation scheme.
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2561) 
2562)     This is a [`click`][CLICK]-powered command-line interface function,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2563)     and not intended for programmatic use.  See the
2564)     derivepassphrase-vault(1) manpage for full documentation of the
2565)     interface.  (See also [`click.testing.CliRunner`][] for controlled,
2566)     programmatic invocation.)
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2567) 
Marco Ricci Update all URLs to stable a...

Marco Ricci authored 3 months ago

2568)     [CLICK]: https://pypi.org/package/click/
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2569) 
2570)     Parameters:
2571)         ctx (click.Context):
2572)             The `click` context.
2573) 
2574)     Other Parameters:
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2575)         service:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2576)             A service name.  Required, unless operating on global
2577)             settings or importing/exporting settings.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2578)         use_phrase:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2579)             Command-line argument `-p`/`--phrase`.  If given, query the
2580)             user for a passphrase instead of an SSH key.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2581)         use_key:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2582)             Command-line argument `-k`/`--key`.  If given, query the
2583)             user for an SSH key instead of a passphrase.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2584)         length:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2585)             Command-line argument `-l`/`--length`.  Override the default
2586)             length of the generated passphrase.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2587)         repeat:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2588)             Command-line argument `-r`/`--repeat`.  Override the default
2589)             repetition limit if positive, or disable the repetition
2590)             limit if 0.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2591)         lower:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2592)             Command-line argument `--lower`.  Require a given amount of
2593)             ASCII lowercase characters if positive, else forbid ASCII
2594)             lowercase characters if 0.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2595)         upper:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2596)             Command-line argument `--upper`.  Same as `lower`, but for
2597)             ASCII uppercase characters.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2598)         number:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2599)             Command-line argument `--number`.  Same as `lower`, but for
2600)             ASCII digits.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2601)         space:
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

2602)             Command-line argument `--space`.  Same as `lower`, but for
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2603)             the space character.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2604)         dash:
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

2605)             Command-line argument `--dash`.  Same as `lower`, but for
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2606)             the hyphen-minus and underscore characters.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2607)         symbol:
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

2608)             Command-line argument `--symbol`.  Same as `lower`, but for
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2609)             all other ASCII printable characters (except backquote).
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2610)         edit_notes:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2611)             Command-line argument `-n`/`--notes`.  If given, spawn an
2612)             editor to edit notes for `service`.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2613)         store_config_only:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2614)             Command-line argument `-c`/`--config`.  If given, saves the
2615)             other given settings (`--key`, ..., `--symbol`) to the
2616)             configuration file, either specifically for `service` or as
2617)             global settings.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2618)         delete_service_settings:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2619)             Command-line argument `-x`/`--delete`.  If given, removes
2620)             the settings for `service` from the configuration file.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2621)         delete_globals:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2622)             Command-line argument `--delete-globals`.  If given, removes
2623)             the global settings from the configuration file.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2624)         clear_all_settings:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2625)             Command-line argument `-X`/`--clear`.  If given, removes all
2626)             settings from the configuration file.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2627)         export_settings:
2628)             Command-line argument `-e`/`--export`.  If a file object,
2629)             then it must be open for writing and accept `str` inputs.
2630)             Otherwise, a filename to open for writing.  Using `-` for
2631)             standard output is supported.
2632)         import_settings:
2633)             Command-line argument `-i`/`--import`.  If a file object, it
2634)             must be open for reading and yield `str` values.  Otherwise,
2635)             a filename to open for reading.  Using `-` for standard
2636)             input is supported.
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

2637)         overwrite_config:
2638)             Command-line arguments `--overwrite-existing` (True) and
2639)             `--merge-existing` (False).  Controls whether config saving
2640)             and config importing overwrite existing configurations, or
2641)             merge them section-wise instead.
Marco Ricci Allow unsetting settings wh...

Marco Ricci authored 2 weeks ago

2642)         unset_settings:
2643)             Command-line argument `--unset`.  If given together with
2644)             `--config`, unsets the specified settings (in addition to
2645)             any other changes requested).
Marco Ricci Support exporting the `vaul...

Marco Ricci authored 2 weeks ago

2646)         export_as:
2647)             Command-line argument `--export-as`.  If given together with
2648)             `--export`, selects the format to export the current
2649)             configuration as: JSON ("json", default) or POSIX sh ("sh").
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2650) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2651)     """
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

2652)     logger = logging.getLogger(PROG_NAME)
2653)     deprecation = logging.getLogger(PROG_NAME + '.deprecation')
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2654)     service_metavar = _msg.TranslatedString(_msg.Label.VAULT_METAVAR_SERVICE)
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2655)     options_in_group: dict[type[click.Option], list[click.Option]] = {}
2656)     params_by_str: dict[str, click.Parameter] = {}
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2657)     for param in ctx.command.params:
2658)         if isinstance(param, click.Option):
2659)             group: type[click.Option]
Marco Ricci Add support for Python 3.9

Marco Ricci authored 3 months ago

2660)             # Use match/case here once Python 3.9 becomes unsupported.
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

2661)             if isinstance(param, PassphraseGenerationOption):
2662)                 group = PassphraseGenerationOption
Marco Ricci Add support for Python 3.9

Marco Ricci authored 3 months ago

2663)             elif isinstance(param, ConfigurationOption):
2664)                 group = ConfigurationOption
2665)             elif isinstance(param, StorageManagementOption):
2666)                 group = StorageManagementOption
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

2667)             elif isinstance(param, LoggingOption):
2668)                 group = LoggingOption
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

2669)             elif isinstance(param, CompatibilityOption):
2670)                 group = CompatibilityOption
Marco Ricci Fix coverage

Marco Ricci authored 1 week ago

2671)             elif isinstance(param, StandardOption):  # pragma: no branch
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

2672)                 group = StandardOption
Marco Ricci Fix coverage

Marco Ricci authored 1 week ago

2673)             elif isinstance(param, OptionGroupOption):  # pragma: no cover
Marco Ricci Add support for Python 3.9

Marco Ricci authored 3 months ago

2674)                 raise AssertionError(  # noqa: DOC501,TRY003,TRY004
2675)                     f'Unknown option group for {param!r}'  # noqa: EM102
2676)                 )
Marco Ricci Fix coverage

Marco Ricci authored 1 week ago

2677)             else:  # pragma: no cover
Marco Ricci Add support for Python 3.9

Marco Ricci authored 3 months ago

2678)                 group = click.Option
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2679)             options_in_group.setdefault(group, []).append(param)
2680)         params_by_str[param.human_readable_name] = param
2681)         for name in param.opts + param.secondary_opts:
2682)             params_by_str[name] = param
2683) 
Marco Ricci Rewrite incompatible option...

Marco Ricci authored 3 weeks ago

2684)     @functools.cache
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 5 months ago

2685)     def is_param_set(param: click.Parameter) -> bool:
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2686)         return bool(ctx.params.get(param.human_readable_name))
2687) 
Marco Ricci Make the mutually exclusive...

Marco Ricci authored 2 weeks ago

2688)     def option_name(param: click.Parameter | str) -> str:
2689)         # Annoyingly, `param.human_readable_name` contains the *function*
2690)         # parameter name, not the list of option names.  *Those* are
2691)         # stashed in the `.opts` and `.secondary_opts` attributes, which
2692)         # are visible in the `.to_info_dict()` output, but not otherwise
2693)         # documented.
2694)         param = params_by_str[param] if isinstance(param, str) else param
2695)         names = [param.human_readable_name, *param.opts, *param.secondary_opts]
2696)         option_names = [n for n in names if n.startswith('--')]
2697)         return min(option_names, key=len)
2698) 
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2699)     def check_incompatible_options(
Marco Ricci Rewrite incompatible option...

Marco Ricci authored 3 weeks ago

2700)         param1: click.Parameter | str,
2701)         param2: click.Parameter | str,
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2702)     ) -> None:
Marco Ricci Rewrite incompatible option...

Marco Ricci authored 3 weeks ago

2703)         param1 = params_by_str[param1] if isinstance(param1, str) else param1
2704)         param2 = params_by_str[param2] if isinstance(param2, str) else param2
2705)         if param1 == param2:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2706)             return
Marco Ricci Rewrite incompatible option...

Marco Ricci authored 3 weeks ago

2707)         if not is_param_set(param1):
2708)             return
2709)         if is_param_set(param2):
Marco Ricci Make the mutually exclusive...

Marco Ricci authored 2 weeks ago

2710)             param1_str = option_name(param1)
2711)             param2_str = option_name(param2)
Marco Ricci Rewrite incompatible option...

Marco Ricci authored 3 weeks ago

2712)             raise click.BadOptionUsage(
Marco Ricci Make the mutually exclusive...

Marco Ricci authored 2 weeks ago

2713)                 param1_str,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2714)                 str(
2715)                     _msg.TranslatedString(
2716)                         _msg.ErrMsgTemplate.PARAMS_MUTUALLY_EXCLUSIVE,
2717)                         param1=param1_str,
2718)                         param2=param2_str,
2719)                     )
2720)                 ),
Marco Ricci Make the mutually exclusive...

Marco Ricci authored 2 weeks ago

2721)                 ctx=ctx,
Marco Ricci Rewrite incompatible option...

Marco Ricci authored 3 weeks ago

2722)             )
2723)         return
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2724) 
Marco Ricci Force logging calls in erro...

Marco Ricci authored 1 week ago

2725)     def err(msg: Any, /, **kwargs: Any) -> NoReturn:  # noqa: ANN401
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

2726)         stacklevel = kwargs.pop('stacklevel', 1)
2727)         stacklevel += 1
Marco Ricci Force logging calls in erro...

Marco Ricci authored 1 week ago

2728)         logger.error(msg, stacklevel=stacklevel, **kwargs)
Marco Ricci Use better error message ha...

Marco Ricci authored 4 months ago

2729)         ctx.exit(1)
2730) 
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 5 months ago

2731)     def get_config() -> _types.VaultConfig:
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2732)         try:
2733)             return _load_config()
2734)         except FileNotFoundError:
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

2735)             try:
2736)                 backup_config, exc = _migrate_and_load_old_config()
2737)             except FileNotFoundError:
2738)                 return {'services': {}}
Marco Ricci Make obtaining the compatib...

Marco Ricci authored 3 weeks ago

2739)             old_name = os.path.basename(
2740)                 _config_filename(subsystem='old settings.json')
2741)             )
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

2742)             new_name = os.path.basename(_config_filename(subsystem='vault'))
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

2743)             deprecation.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2744)                 _msg.TranslatedString(
2745)                     _msg.WarnMsgTemplate.V01_STYLE_CONFIG,
2746)                     old=old_name,
2747)                     new=new_name,
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

2748)                 ),
2749)             )
2750)             if isinstance(exc, OSError):
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

2751)                 logger.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2752)                     _msg.TranslatedString(
2753)                         _msg.WarnMsgTemplate.FAILED_TO_MIGRATE_CONFIG,
2754)                         path=new_name,
2755)                         error=exc.strerror,
2756)                         filename=exc.filename,
2757)                     ).maybe_without_filename(),
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

2758)                 )
2759)             else:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2760)                 deprecation.info(
2761)                     _msg.TranslatedString(
2762)                         _msg.InfoMsgTemplate.SUCCESSFULLY_MIGRATED,
2763)                         path=new_name,
2764)                     ),
2765)                 )
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

2766)             return backup_config
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

2767)         except OSError as exc:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2768)             err(
2769)                 _msg.TranslatedString(
2770)                     _msg.ErrMsgTemplate.CANNOT_LOAD_VAULT_SETTINGS,
2771)                     error=exc.strerror,
2772)                     filename=exc.filename,
2773)                 ).maybe_without_filename(),
2774)             )
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

2775)         except Exception as exc:  # noqa: BLE001
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2776)             err(
2777)                 _msg.TranslatedString(
2778)                     _msg.ErrMsgTemplate.CANNOT_LOAD_VAULT_SETTINGS,
2779)                     error=str(exc),
2780)                     filename=None,
2781)                 ).maybe_without_filename(),
2782)                 exc_info=exc,
2783)             )
Marco Ricci Use better error message ha...

Marco Ricci authored 4 months ago

2784) 
2785)     def put_config(config: _types.VaultConfig, /) -> None:
2786)         try:
2787)             _save_config(config)
Marco Ricci Document and handle other e...

Marco Ricci authored 4 months ago

2788)         except OSError as exc:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2789)             err(
2790)                 _msg.TranslatedString(
2791)                     _msg.ErrMsgTemplate.CANNOT_STORE_VAULT_SETTINGS,
2792)                     error=exc.strerror,
2793)                     filename=exc.filename,
2794)                 ).maybe_without_filename(),
2795)             )
Marco Ricci Use better error message ha...

Marco Ricci authored 4 months ago

2796)         except Exception as exc:  # noqa: BLE001
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2797)             err(
2798)                 _msg.TranslatedString(
2799)                     _msg.ErrMsgTemplate.CANNOT_STORE_VAULT_SETTINGS,
2800)                     error=str(exc),
2801)                     filename=None,
2802)                 ).maybe_without_filename(),
2803)                 exc_info=exc,
2804)             )
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2805) 
Marco Ricci Introduce a central user co...

Marco Ricci authored 3 weeks ago

2806)     def get_user_config() -> dict[str, Any]:
2807)         try:
2808)             return _load_user_config()
2809)         except FileNotFoundError:
2810)             return {}
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

2811)         except OSError as exc:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2812)             err(
2813)                 _msg.TranslatedString(
2814)                     _msg.ErrMsgTemplate.CANNOT_LOAD_USER_CONFIG,
2815)                     error=exc.strerror,
2816)                     filename=exc.filename,
2817)                 ).maybe_without_filename(),
2818)             )
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

2819)         except Exception as exc:  # noqa: BLE001
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2820)             err(
2821)                 _msg.TranslatedString(
2822)                     _msg.ErrMsgTemplate.CANNOT_LOAD_USER_CONFIG,
2823)                     error=str(exc),
2824)                     filename=None,
2825)                 ).maybe_without_filename(),
2826)                 exc_info=exc,
2827)             )
Marco Ricci Introduce a central user co...

Marco Ricci authored 3 weeks ago

2828) 
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 5 months ago

2829)     configuration: _types.VaultConfig
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2830) 
2831)     check_incompatible_options('--phrase', '--key')
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2832)     for group in (ConfigurationOption, StorageManagementOption):
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2833)         for opt in options_in_group[group]:
2834)             if opt != params_by_str['--config']:
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

2835)                 for other_opt in options_in_group[PassphraseGenerationOption]:
Marco Ricci Rewrite incompatible option...

Marco Ricci authored 3 weeks ago

2836)                     check_incompatible_options(opt, other_opt)
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2837) 
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2838)     for group in (ConfigurationOption, StorageManagementOption):
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2839)         for opt in options_in_group[group]:
Marco Ricci Rewrite incompatible option...

Marco Ricci authored 3 weeks ago

2840)             for other_opt in options_in_group[ConfigurationOption]:
2841)                 check_incompatible_options(opt, other_opt)
2842)             for other_opt in options_in_group[StorageManagementOption]:
2843)                 check_incompatible_options(opt, other_opt)
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

2844)     sv_or_global_options = options_in_group[PassphraseGenerationOption]
Marco Ricci Correctly model vault globa...

Marco Ricci authored 2 months ago

2845)     for param in sv_or_global_options:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2846)         if is_param_set(param) and not (
2847)             service or is_param_set(params_by_str['--config'])
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2848)         ):
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2849)             err_msg = _msg.TranslatedString(
2850)                 _msg.ErrMsgTemplate.PARAMS_NEEDS_SERVICE_OR_CONFIG,
2851)                 param=param.opts[0],
2852)                 service_metavar=service_metavar,
2853)             )
2854)             raise click.UsageError(str(err_msg))  # noqa: DOC501
Marco Ricci Correctly model vault globa...

Marco Ricci authored 2 months ago

2855)     sv_options = [params_by_str['--notes'], params_by_str['--delete']]
2856)     for param in sv_options:
2857)         if is_param_set(param) and not service:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2858)             err_msg = _msg.TranslatedString(
2859)                 _msg.ErrMsgTemplate.PARAMS_NEEDS_SERVICE,
2860)                 param=param.opts[0],
2861)                 service_metavar=service_metavar,
2862)             )
2863)             raise click.UsageError(str(err_msg))
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2864)     no_sv_options = [
2865)         params_by_str['--delete-globals'],
2866)         params_by_str['--clear'],
2867)         *options_in_group[StorageManagementOption],
2868)     ]
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2869)     for param in no_sv_options:
2870)         if is_param_set(param) and service:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2871)             err_msg = _msg.TranslatedString(
2872)                 _msg.ErrMsgTemplate.PARAMS_NO_SERVICE,
2873)                 param=param.opts[0],
2874)                 service_metavar=service_metavar,
2875)             )
2876)             raise click.UsageError(str(err_msg))
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

2877) 
Marco Ricci Introduce a central user co...

Marco Ricci authored 3 weeks ago

2878)     user_config = get_user_config()
2879) 
Marco Ricci Warn the user upon supplyin...

Marco Ricci authored 2 months ago

2880)     if service == '':  # noqa: PLC1901
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

2881)         logger.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2882)             _msg.TranslatedString(
2883)                 _msg.WarnMsgTemplate.EMPTY_SERVICE_NOT_SUPPORTED,
2884)                 service_metavar=service_metavar,
2885)             )
Marco Ricci Warn the user upon supplyin...

Marco Ricci authored 2 months ago

2886)         )
2887) 
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

2888)     if edit_notes:
2889)         assert service is not None
2890)         configuration = get_config()
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2891)         text = DEFAULT_NOTES_TEMPLATE + configuration['services'].get(
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 5 months ago

2892)             service, cast(_types.VaultConfigServicesSettings, {})
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2893)         ).get('notes', '')
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

2894)         notes_value = click.edit(text=text)
2895)         if notes_value is not None:
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

2896)             notes_lines = collections.deque(notes_value.splitlines(True))  # noqa: FBT003
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

2897)             while notes_lines:
2898)                 line = notes_lines.popleft()
2899)                 if line.startswith(DEFAULT_NOTES_MARKER):
2900)                     notes_value = ''.join(notes_lines)
2901)                     break
2902)             else:
2903)                 if not notes_value.strip():
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2904)                     err(
2905)                         _msg.TranslatedString(
2906)                             _msg.ErrMsgTemplate.USER_ABORTED_EDIT
2907)                         )
2908)                     )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

2909)             configuration['services'].setdefault(service, {})['notes'] = (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2910)                 notes_value.strip('\n')
2911)             )
Marco Ricci Use better error message ha...

Marco Ricci authored 4 months ago

2912)             put_config(configuration)
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

2913)     elif delete_service_settings:
2914)         assert service is not None
2915)         configuration = get_config()
2916)         if service in configuration['services']:
2917)             del configuration['services'][service]
Marco Ricci Use better error message ha...

Marco Ricci authored 4 months ago

2918)             put_config(configuration)
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

2919)     elif delete_globals:
2920)         configuration = get_config()
2921)         if 'global' in configuration:
2922)             del configuration['global']
Marco Ricci Use better error message ha...

Marco Ricci authored 4 months ago

2923)             put_config(configuration)
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

2924)     elif clear_all_settings:
Marco Ricci Use better error message ha...

Marco Ricci authored 4 months ago

2925)         put_config({'services': {}})
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

2926)     elif import_settings:
2927)         try:
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

2928)             # TODO(the-13th-letter): keep track of auto-close; try
2929)             # os.dup if feasible
Marco Ricci Document handling of file o...

Marco Ricci authored 3 weeks ago

2930)             infile = cast(
2931)                 TextIO,
2932)                 (
2933)                     import_settings
2934)                     if hasattr(import_settings, 'close')
2935)                     else click.open_file(os.fspath(import_settings), 'rt')
2936)                 ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2937)             )
Marco Ricci Document handling of file o...

Marco Ricci authored 3 weeks ago

2938)             # Don't specifically catch TypeError or ValueError here if
2939)             # the passed-in fileobj is not a readable text stream.  This
2940)             # will never happen on the command-line (thanks to `click`),
2941)             # and for programmatic use, our caller may want accurate
2942)             # error information.
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

2943)             with infile:
2944)                 maybe_config = json.load(infile)
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

2945)         except json.JSONDecodeError as exc:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2946)             err(
2947)                 _msg.TranslatedString(
2948)                     _msg.ErrMsgTemplate.CANNOT_DECODEIMPORT_VAULT_SETTINGS,
2949)                     error=exc,
2950)                 )
2951)             )
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

2952)         except OSError as exc:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2953)             err(
2954)                 _msg.TranslatedString(
2955)                     _msg.ErrMsgTemplate.CANNOT_IMPORT_VAULT_SETTINGS,
2956)                     error=exc.strerror,
2957)                     filename=exc.filename,
2958)                 ).maybe_without_filename()
2959)             )
Marco Ricci Signal and list falsy value...

Marco Ricci authored 3 months ago

2960)         cleaned = _types.clean_up_falsy_vault_config_values(maybe_config)
2961)         if not _types.is_vault_config(maybe_config):
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2962)             err(
2963)                 _msg.TranslatedString(
2964)                     _msg.ErrMsgTemplate.CANNOT_IMPORT_VAULT_SETTINGS,
2965)                     error=_msg.TranslatedString(
2966)                         _msg.ErrMsgTemplate.INVALID_VAULT_CONFIG,
2967)                         config=maybe_config,
2968)                     ),
2969)                     filename=None,
2970)                 ).maybe_without_filename()
2971)             )
Marco Ricci Signal and list falsy value...

Marco Ricci authored 3 months ago

2972)         assert cleaned is not None
2973)         for step in cleaned:
2974)             # These are never fatal errors, because the semantics of
2975)             # vault upon encountering these settings are ill-specified,
2976)             # but not ill-defined.
2977)             if step.action == 'replace':
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

2978)                 logger.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2979)                     _msg.TranslatedString(
2980)                         _msg.WarnMsgTemplate.STEP_REPLACE_INVALID_VALUE,
2981)                         old=json.dumps(step.old_value),
2982)                         path=_types.json_path(step.path),
2983)                         new=json.dumps(step.new_value),
2984)                     ),
Marco Ricci Signal and list falsy value...

Marco Ricci authored 3 months ago

2985)                 )
2986)             else:
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

2987)                 logger.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2988)                     _msg.TranslatedString(
2989)                         _msg.WarnMsgTemplate.STEP_REMOVE_INEFFECTIVE_VALUE,
2990)                         path=_types.json_path(step.path),
2991)                         old=json.dumps(step.old_value),
2992)                     ),
Marco Ricci Signal and list falsy value...

Marco Ricci authored 3 months ago

2993)                 )
Marco Ricci Warn the user upon supplyin...

Marco Ricci authored 2 months ago

2994)         if '' in maybe_config['services']:
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

2995)             logger.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2996)                 _msg.TranslatedString(
2997)                     _msg.WarnMsgTemplate.EMPTY_SERVICE_SETTINGS_INACCESSIBLE,
2998)                     service_metavar=service_metavar,
2999)                     PROG_NAME=PROG_NAME,
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

3000)                 ),
Marco Ricci Warn the user upon supplyin...

Marco Ricci authored 2 months ago

3001)             )
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

3002)         try:
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

3003)             _check_for_misleading_passphrase(
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

3004)                 ('global',),
3005)                 cast(dict[str, Any], maybe_config.get('global', {})),
3006)                 main_config=user_config,
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

3007)             )
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

3008)             for key, value in maybe_config['services'].items():
3009)                 _check_for_misleading_passphrase(
3010)                     ('services', key),
3011)                     cast(dict[str, Any], value),
3012)                     main_config=user_config,
3013)                 )
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

3014)         except AssertionError as exc:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3015)             err(
3016)                 _msg.TranslatedString(
3017)                     _msg.ErrMsgTemplate.INVALID_USER_CONFIG,
3018)                     error=exc,
3019)                     filename=None,
3020)                 ).maybe_without_filename(),
3021)             )
Marco Ricci Fix empty key handling in `...

Marco Ricci authored 3 weeks ago

3022)         global_obj = maybe_config.get('global', {})
3023)         has_key = _types.js_truthiness(global_obj.get('key'))
3024)         has_phrase = _types.js_truthiness(global_obj.get('phrase'))
3025)         if has_key and has_phrase:
3026)             logger.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3027)                 _msg.TranslatedString(
3028)                     _msg.WarnMsgTemplate.GLOBAL_PASSPHRASE_INEFFECTIVE,
3029)                 )
Marco Ricci Fix empty key handling in `...

Marco Ricci authored 3 weeks ago

3030)             )
3031)         for service_name, service_obj in maybe_config['services'].items():
3032)             has_key = _types.js_truthiness(
3033)                 service_obj.get('key')
3034)             ) or _types.js_truthiness(global_obj.get('key'))
3035)             has_phrase = _types.js_truthiness(
3036)                 service_obj.get('phrase')
3037)             ) or _types.js_truthiness(global_obj.get('phrase'))
3038)             if has_key and has_phrase:
3039)                 logger.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3040)                     _msg.TranslatedString(
3041)                         _msg.WarnMsgTemplate.SERVICE_PASSPHRASE_INEFFECTIVE,
3042)                         service=json.dumps(service_name),
Marco Ricci Fix empty key handling in `...

Marco Ricci authored 3 weeks ago

3043)                     ),
3044)                 )
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

3045)         if overwrite_config:
3046)             put_config(maybe_config)
3047)         else:
3048)             configuration = get_config()
3049)             merged_config: collections.ChainMap[str, Any] = (
3050)                 collections.ChainMap(
3051)                     {
3052)                         'services': collections.ChainMap(
3053)                             maybe_config['services'],
3054)                             configuration['services'],
3055)                         ),
3056)                     },
3057)                     {'global': maybe_config['global']}
3058)                     if 'global' in maybe_config
3059)                     else {},
3060)                     {'global': configuration['global']}
3061)                     if 'global' in configuration
3062)                     else {},
3063)                 )
3064)             )
3065)             new_config: Any = {
3066)                 k: dict(v) if isinstance(v, collections.ChainMap) else v
3067)                 for k, v in sorted(merged_config.items())
3068)             }
3069)             assert _types.is_vault_config(new_config)
3070)             put_config(new_config)
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3071)     elif export_settings:
3072)         configuration = get_config()
3073)         try:
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

3074)             # TODO(the-13th-letter): keep track of auto-close; try
3075)             # os.dup if feasible
Marco Ricci Document handling of file o...

Marco Ricci authored 3 weeks ago

3076)             outfile = cast(
3077)                 TextIO,
3078)                 (
3079)                     export_settings
3080)                     if hasattr(export_settings, 'close')
3081)                     else click.open_file(os.fspath(export_settings), 'wt')
3082)                 ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

3083)             )
Marco Ricci Document handling of file o...

Marco Ricci authored 3 weeks ago

3084)             # Don't specifically catch TypeError or ValueError here if
3085)             # the passed-in fileobj is not a writable text stream.  This
3086)             # will never happen on the command-line (thanks to `click`),
3087)             # and for programmatic use, our caller may want accurate
3088)             # error information.
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3089)             with outfile:
Marco Ricci Support exporting the `vaul...

Marco Ricci authored 2 weeks ago

3090)                 if export_as == 'sh':
3091)                     this_ctx = ctx
3092)                     prog_name_pieces = collections.deque([
3093)                         this_ctx.info_name or 'vault',
3094)                     ])
3095)                     while (
3096)                         this_ctx.parent is not None
3097)                         and this_ctx.parent.info_name is not None
3098)                     ):
3099)                         prog_name_pieces.appendleft(this_ctx.parent.info_name)
3100)                         this_ctx = this_ctx.parent
3101)                     _print_config_as_sh_script(
3102)                         configuration,
3103)                         outfile=outfile,
3104)                         prog_name_list=prog_name_pieces,
3105)                     )
3106)                 else:
3107)                     json.dump(configuration, outfile)
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

3108)         except OSError as exc:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3109)             err(
3110)                 _msg.TranslatedString(
3111)                     _msg.ErrMsgTemplate.CANNOT_EXPORT_VAULT_SETTINGS,
3112)                     error=exc.strerror,
3113)                     filename=exc.filename,
3114)                 ).maybe_without_filename(),
3115)             )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3116)     else:
3117)         configuration = get_config()
3118)         # This block could be type checked more stringently, but this
3119)         # would probably involve a lot of code repetition.  Since we
3120)         # have a type guarding function anyway, assert that we didn't
3121)         # make any mistakes at the end instead.
3122)         global_keys = {'key', 'phrase'}
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

3123)         service_keys = {
3124)             'key',
3125)             'phrase',
3126)             'length',
3127)             'repeat',
3128)             'lower',
3129)             'upper',
3130)             'number',
3131)             'space',
3132)             'dash',
3133)             'symbol',
3134)         }
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3135)         settings: collections.ChainMap[str, Any] = collections.ChainMap(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

3136)             {
3137)                 k: v
3138)                 for k, v in locals().items()
3139)                 if k in service_keys and v is not None
3140)             },
3141)             cast(
3142)                 dict[str, Any],
3143)                 configuration['services'].get(service or '', {}),
3144)             ),
3145)             cast(dict[str, Any], configuration.get('global', {})),
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3146)         )
3147)         if use_key:
3148)             try:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

3149)                 key = base64.standard_b64encode(_select_ssh_key()).decode(
3150)                     'ASCII'
3151)                 )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3152)             except IndexError:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3153)                 err(
3154)                     _msg.TranslatedString(
3155)                         _msg.ErrMsgTemplate.USER_ABORTED_SSH_KEY_SELECTION
3156)                     ),
3157)                 )
Marco Ricci Document and handle other e...

Marco Ricci authored 4 months ago

3158)             except KeyError:
Marco Ricci Fail gracefully if UNIX dom...

Marco Ricci authored 3 months ago

3159)                 err(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3160)                     _msg.TranslatedString(
3161)                         _msg.ErrMsgTemplate.NO_SSH_AGENT_FOUND
3162)                     ),
3163)                 )
3164)             except LookupError:
3165)                 err(
3166)                     _msg.TranslatedString(
3167)                         _msg.ErrMsgTemplate.NO_SUITABLE_SSH_KEYS,
3168)                         PROG_NAME=PROG_NAME,
3169)                     )
Marco Ricci Fail gracefully if UNIX dom...

Marco Ricci authored 3 months ago

3170)                 )
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3171)             except NotImplementedError:
3172)                 err(_msg.TranslatedString(_msg.ErrMsgTemplate.NO_AF_UNIX))
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

3173)             except OSError as exc:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3174)                 err(
3175)                     _msg.TranslatedString(
3176)                         _msg.ErrMsgTemplate.CANNOT_CONNECT_TO_AGENT,
3177)                         error=exc.strerror,
3178)                         filename=exc.filename,
3179)                     ).maybe_without_filename(),
3180)                 )
3181)             except ssh_agent.SSHAgentFailedError as exc:
3182)                 err(
3183)                     _msg.TranslatedString(
3184)                         _msg.ErrMsgTemplate.AGENT_REFUSED_LIST_KEYS
3185)                     ),
3186)                     exc_info=exc,
3187)                 )
3188)             except RuntimeError as exc:
3189)                 err(
3190)                     _msg.TranslatedString(
3191)                         _msg.ErrMsgTemplate.CANNOT_UNDERSTAND_AGENT
3192)                     ),
3193)                     exc_info=exc,
3194)                 )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3195)         elif use_phrase:
3196)             maybe_phrase = _prompt_for_passphrase()
3197)             if not maybe_phrase:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3198)                 err(
3199)                     _msg.TranslatedString(
3200)                         _msg.ErrMsgTemplate.USER_ABORTED_PASSPHRASE
3201)                     )
3202)                 )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3203)             else:
3204)                 phrase = maybe_phrase
3205)         if store_config_only:
3206)             view: collections.ChainMap[str, Any]
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

3207)             view = (
3208)                 collections.ChainMap(*settings.maps[:2])
3209)                 if service
Marco Ricci Fix missing consideration o...

Marco Ricci authored 2 months ago

3210)                 else collections.ChainMap(settings.maps[0], settings.maps[2])
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

3211)             )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3212)             if use_key:
3213)                 view['key'] = key
3214)             elif use_phrase:
Marco Ricci Fix missing consideration o...

Marco Ricci authored 2 months ago

3215)                 view['phrase'] = phrase
3216)                 settings_type = 'service' if service else 'global'
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

3217)                 try:
3218)                     _check_for_misleading_passphrase(
3219)                         ('services', service) if service else ('global',),
3220)                         {'phrase': phrase},
3221)                         main_config=user_config,
3222)                     )
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

3223)                 except AssertionError as exc:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3224)                     err(
3225)                         _msg.TranslatedString(
3226)                             _msg.ErrMsgTemplate.INVALID_USER_CONFIG,
3227)                             error=exc,
3228)                             filename=None,
3229)                         ).maybe_without_filename(),
3230)                     )
Marco Ricci Fix missing consideration o...

Marco Ricci authored 2 months ago

3231)                 if 'key' in settings:
Marco Ricci Fix empty key handling in `...

Marco Ricci authored 3 weeks ago

3232)                     if service:
3233)                         logger.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3234)                             _msg.TranslatedString(
3235)                                 _msg.WarnMsgTemplate.SERVICE_PASSPHRASE_INEFFECTIVE,
3236)                                 service=json.dumps(service),
3237)                             )
Marco Ricci Fix empty key handling in `...

Marco Ricci authored 3 weeks ago

3238)                         )
3239)                     else:
3240)                         logger.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3241)                             _msg.TranslatedString(
3242)                                 _msg.WarnMsgTemplate.GLOBAL_PASSPHRASE_INEFFECTIVE
3243)                             )
Marco Ricci Fix empty key handling in `...

Marco Ricci authored 3 weeks ago

3244)                         )
Marco Ricci Allow unsetting settings wh...

Marco Ricci authored 2 weeks ago

3245)             if not view.maps[0] and not unset_settings:
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

3246)                 settings_type = 'service' if service else 'global'
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3247)                 err_msg = _msg.TranslatedString(
3248)                     _msg.ErrMsgTemplate.CANNOT_UPDATE_SETTINGS_NO_SETTINGS,
3249)                     settings_type=settings_type,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

3250)                 )
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3251)                 raise click.UsageError(str(err_msg))
Marco Ricci Allow unsetting settings wh...

Marco Ricci authored 2 weeks ago

3252)             for setting in unset_settings:
3253)                 if setting in view.maps[0]:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3254)                     err_msg = _msg.TranslatedString(
3255)                         _msg.ErrMsgTemplate.SET_AND_UNSET_SAME_SETTING,
3256)                         setting=setting,
Marco Ricci Allow unsetting settings wh...

Marco Ricci authored 2 weeks ago

3257)                     )
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3258)                     raise click.UsageError(str(err_msg))
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

3259)             subtree: dict[str, Any] = (
3260)                 configuration['services'].setdefault(service, {})  # type: ignore[assignment]
3261)                 if service
3262)                 else configuration.setdefault('global', {})
3263)             )
3264)             if overwrite_config:
3265)                 subtree.clear()
Marco Ricci Allow unsetting settings wh...

Marco Ricci authored 2 weeks ago

3266)             else:
3267)                 for setting in unset_settings:
3268)                     subtree.pop(setting, None)
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

3269)             subtree.update(view)
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 5 months ago

3270)             assert _types.is_vault_config(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

3271)                 configuration
Marco Ricci Fix error message capitaliz...

Marco Ricci authored 4 months ago

3272)             ), f'Invalid vault configuration: {configuration!r}'
Marco Ricci Fix error bubbling in outda...

Marco Ricci authored 4 months ago

3273)             put_config(configuration)
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3274)         else:
3275)             if not service:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3276)                 err_msg = _msg.TranslatedString(
3277)                     _msg.ErrMsgTemplate.SERVICE_REQUIRED,
3278)                     service_metavar=_msg.TranslatedString(
3279)                         _msg.Label.VAULT_METAVAR_SERVICE
3280)                     ),
3281)                 )
3282)                 raise click.UsageError(str(err_msg))
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

3283)             kwargs: dict[str, Any] = {
3284)                 k: v
3285)                 for k, v in settings.items()
3286)                 if k in service_keys and v is not None
3287)             }
3288) 
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

3289)             if use_phrase:
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

3290)                 try:
3291)                     _check_for_misleading_passphrase(
3292)                         _ORIGIN.INTERACTIVE,
3293)                         {'phrase': phrase},
3294)                         main_config=user_config,
3295)                     )
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

3296)                 except AssertionError as exc:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3297)                     err(
3298)                         _msg.TranslatedString(
3299)                             _msg.ErrMsgTemplate.INVALID_USER_CONFIG,
3300)                             error=exc,
3301)                             filename=None,
3302)                         ).maybe_without_filename(),
3303)                     )
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

3304) 
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3305)             # If either --key or --phrase are given, use that setting.
3306)             # Otherwise, if both key and phrase are set in the config,
Marco Ricci Align behavior with vault c...

Marco Ricci authored 3 months ago

3307)             # use the key.  Otherwise, if only one of key and phrase is
3308)             # set in the config, use that one.  In all these above
3309)             # cases, set the phrase via vault.Vault.phrase_from_key if
3310)             # a key is given.  Finally, if nothing is set, error out.
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3311)             if use_key or use_phrase:
Marco Ricci Fix formatting, some covera...

Marco Ricci authored 2 weeks ago

3312)                 kwargs['phrase'] = (
3313)                     _key_to_phrase(key, error_callback=err)
3314)                     if use_key
3315)                     else phrase
3316)                 )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3317)             elif kwargs.get('key'):
Marco Ricci Hoist and add tests for int...

Marco Ricci authored 3 weeks ago

3318)                 kwargs['phrase'] = _key_to_phrase(
3319)                     kwargs['key'], error_callback=err
3320)                 )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3321)             elif kwargs.get('phrase'):
3322)                 pass
3323)             else:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3324)                 err_msg = _msg.TranslatedString(
3325)                     _msg.ErrMsgTemplate.NO_KEY_OR_PHRASE
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

3326)                 )
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3327)                 raise click.UsageError(str(err_msg))
Marco Ricci Avoid crashing when overrid...

Marco Ricci authored 5 months ago

3328)             kwargs.pop('key', '')
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 5 months ago

3329)             result = vault.Vault(**kwargs).generate(service)
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3330)             click.echo(result.decode('ASCII'))