43a9458b3a76dbf9a8785d59d297d8366b532fd7
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)         """
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

98)         click.echo(
99)             self.format(record),
100)             err=True,
101)             color=getattr(record, 'color', None),
102)         )
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 4 weeks ago

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

Marco Ricci authored 1 month ago

369)     ctx: click.Context,
370)     /,
371)     param: click.Parameter | None = None,
Marco Ricci Fix usage of `--debug`, `--...

Marco Ricci authored 4 weeks ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 4 weeks ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 4 weeks ago

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

Marco Ricci authored 1 month ago

379) 
380)     """
Marco Ricci Fix usage of `--debug`, `--...

Marco Ricci authored 4 weeks ago

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

Marco Ricci authored 1 month ago

387) 
388) 
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

428) 
429) 
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

430) class StandardOption(OptionGroupOption):
431)     pass
432) 
433) 
Marco Ricci Shift option parsing and gr...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

444) 
445)     [CLICK_ISSUE]: https://github.com/pallets/click/issues/373#issuecomment-515293746
446) 
447)     """
448) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

799)         Args:
800)             ctx:
801)                 The click context.
802)             formatter:
803)                 The formatter for the `--help` listing.
804) 
805)         """
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

990) 
991) 
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

992) def version_option_callback(
993)     ctx: click.Context,
994)     param: click.Parameter,
995)     value: bool,  # noqa: FBT001
Marco Ricci Fix coverage

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 week ago

1023) def color_forcing_callback(
1024)     ctx: click.Context,
1025)     param: click.Parameter,
1026)     value: Any,  # noqa: ANN401
1027) ) -> None:
1028)     """Force the `click` context to honor `NO_COLOR` and `FORCE_COLOR`."""
1029)     del param, value
1030)     if os.environ.get('NO_COLOR'):  # pragma: no cover
1031)         ctx.color = False
1032)     if os.environ.get('FORCE_COLOR'):  # pragma: no cover
1033)         ctx.color = True
1034) 
1035) 
1036) color_forcing_pseudo_option = click.option(
1037)     '--_pseudo-option-color-forcing',
1038)     '_color_forcing',
1039)     is_flag=True,
1040)     is_eager=True,
1041)     expose_value=False,
1042)     hidden=True,
1043)     callback=color_forcing_callback,
1044)     help='(pseudo-option)',
1045) )
1046) 
1047) 
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1048) class LoggingOption(OptionGroupOption):
1049)     """Logging options for the CLI."""
1050) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

1052)     epilog = ''
1053) 
1054) 
Marco Ricci Fix usage of `--debug`, `--...

Marco Ricci authored 4 weeks ago

1055) debug_option = click.option(
1056)     '--debug',
1057)     'logging_level',
1058)     is_flag=True,
1059)     flag_value=logging.DEBUG,
1060)     expose_value=False,
1061)     callback=adjust_logging_level,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

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

Marco Ricci authored 4 weeks ago

1063)     cls=LoggingOption,
1064) )
1065) verbose_option = click.option(
1066)     '-v',
1067)     '--verbose',
1068)     'logging_level',
1069)     is_flag=True,
1070)     flag_value=logging.INFO,
1071)     expose_value=False,
1072)     callback=adjust_logging_level,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

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

Marco Ricci authored 4 weeks ago

1074)     cls=LoggingOption,
1075) )
1076) quiet_option = click.option(
1077)     '-q',
1078)     '--quiet',
1079)     'logging_level',
1080)     is_flag=True,
1081)     flag_value=logging.ERROR,
1082)     expose_value=False,
1083)     callback=adjust_logging_level,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

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

Marco Ricci authored 4 weeks ago

1085)     cls=LoggingOption,
1086) )
1087) 
1088) 
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 month ago

1095) 
1096)     Args:
1097)         f: A callable to decorate.
1098) 
1099)     Returns:
1100)         The decorated callable.
1101) 
1102)     """
Marco Ricci Fix usage of `--debug`, `--...

Marco Ricci authored 4 weeks ago

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

Marco Ricci authored 1 month ago

1104) 
1105) 
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1106) # Top-level
1107) # =========
1108) 
1109) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

1111)     """A helper class to implement the default-to-"vault"-subcommand behavior.
1112) 
1113)     Modifies internal [`click.MultiCommand`][] methods, and thus is both
1114)     an implementation detail and a kludge.
1115) 
1116)     """
1117) 
1118)     def resolve_command(
1119)         self, ctx: click.Context, args: list[str]
1120)     ) -> tuple[str | None, click.Command | None, list[str]]:
1121)         """Resolve a command, but default to "vault" instead of erroring out.
1122) 
1123)         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

1124)         untouched since at least click 3.2.  Subject to the following
1125)         license (3-clause BSD license):
1126) 
1127)             Copyright 2024 Pallets
1128) 
1129)             Redistribution and use in source and binary forms, with or
1130)             without modification, are permitted provided that the following
1131)             conditions are met:
1132) 
1133)              1. Redistributions of source code must retain the above
1134)                 copyright notice, this list of conditions and the following
1135)                 disclaimer.
1136) 
1137)              2. Redistributions in binary form must reproduce the above
1138)                 copyright notice, this list of conditions and the following
1139)                 disclaimer in the documentation and/or other materials
1140)                 provided with the distribution.
1141) 
1142)              3. Neither the name of the copyright holder nor the names of
1143)                 its contributors may be used to endorse or promote products
1144)                 derived from this software without specific prior written
1145)                 permission.
1146) 
1147)             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
1148)             CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
1149)             INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1150)             MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1151)             DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
1152)             CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1153)             SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1154)             LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
1155)             USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
1156)             AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1157)             LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
1158)             IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
1159)             THE POSSIBILITY OF SUCH DAMAGE.
1160) 
1161)         Modifications to this routine are marked with "modifications for
1162)         derivepassphrase".  Furthermore, all "pragma" and "noqa" comments
1163)         are also modifications for derivepassphrase.
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1164) 
1165)         """
1166)         cmd_name = click.utils.make_str(args[0])
1167) 
1168)         # Get the command
1169)         cmd = self.get_command(ctx, cmd_name)
1170) 
1171)         # If we can't find the command but there is a normalization
1172)         # function available, we try with that one.
1173)         if (  # pragma: no cover
1174)             cmd is None and ctx.token_normalize_func is not None
1175)         ):
1176)             cmd_name = ctx.token_normalize_func(cmd_name)
1177)             cmd = self.get_command(ctx, cmd_name)
1178) 
1179)         # If we don't find the command we want to show an error message
1180)         # to the user that it was not provided.  However, there is
1181)         # something else we should do: if the first argument looks like
1182)         # an option we want to kick off parsing again for arguments to
1183)         # resolve things like --help which now should go to the main
1184)         # place.
1185)         if cmd is None and not ctx.resilient_parsing:
1186)             if click.parser.split_opt(cmd_name)[0]:
1187)                 self.parse_args(ctx, ctx.args)
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1188)             ####
1189)             # BEGIN modifications for derivepassphrase
1190)             #
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

1195)                 _msg.TranslatedString(
1196)                     _msg.WarnMsgTemplate.V10_SUBCOMMAND_REQUIRED
1197)                 )
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1198)             )
1199)             cmd_name = 'vault'
1200)             cmd = self.get_command(ctx, cmd_name)
1201)             assert cmd is not None, 'Mandatory subcommand "vault" missing!'
1202)             args = [cmd_name, *args]
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1203)             #
1204)             # END modifications for derivepassphrase
1205)             ####
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 month ago

1209) class _TopLevelCLIEntryPoint(_DefaultToVaultGroup):
1210)     """A minor variation of _DefaultToVaultGroup for the top-level command.
1211) 
1212)     When called as a function, this sets up the environment properly
1213)     before invoking the actual callbacks.  Currently, this means setting
1214)     up the logging subsystem and the delegation of Python warnings to
1215)     the logging subsystem.
1216) 
1217)     The environment setup can be bypassed by calling the `.main` method
1218)     directly.
1219) 
1220)     """
1221) 
1222)     def __call__(  # pragma: no cover
1223)         self,
1224)         *args: Any,  # noqa: ANN401
1225)         **kwargs: Any,  # noqa: ANN401
1226)     ) -> Any:  # noqa: ANN401
1227)         """"""  # noqa: D419
1228)         # Coverage testing is done with the `click.testing` module,
1229)         # which does not use the `__call__` shortcut.  So it is normal
1230)         # that this function is never called, and thus should be
1231)         # excluded from coverage.
1232)         with (
1233)             StandardCLILogging.ensure_standard_logging(),
1234)             StandardCLILogging.ensure_standard_warnings_logging(),
1235)         ):
1236)             return self.main(*args, **kwargs)
1237) 
1238) 
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 3 months ago

1240)     context_settings={
1241)         'help_option_names': ['-h', '--help'],
1242)         'ignore_unknown_options': True,
1243)         'allow_interspersed_args': False,
1244)     },
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

1248)     help=(
1249)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_01),
1250)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_02),
1251)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_03),
1252)     ),
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 1 week ago

1254) @version_option
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1255) @color_forcing_pseudo_option
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 3 months ago

1259)     """Derive a strong passphrase, deterministically, from a master secret.
1260) 
1261)     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

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

Marco Ricci authored 3 months ago

1264)     [`click.testing.CliRunner`][] for controlled, programmatic
1265)     invocation.)
1266) 
Marco Ricci Update all URLs to stable a...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 month ago

1272)         deprecation.warning(
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1273)             _msg.TranslatedString(
1274)                 _msg.WarnMsgTemplate.V10_SUBCOMMAND_REQUIRED
1275)             ),
1276)             extra={'color': ctx.color},
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1277)         )
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1278)         # See definition of click.Group.invoke, non-chained case.
1279)         with ctx:
1280)             sub_ctx = derivepassphrase_vault.make_context(
1281)                 'vault', ctx.args, parent=ctx
1282)             )
1283)             with sub_ctx:
1284)                 return derivepassphrase_vault.invoke(sub_ctx)
1285)     return None
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1286) 
1287) 
1288) # Exporter
1289) # ========
1290) 
1291) 
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1292) @derivepassphrase.group(
1293)     'export',
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1294)     context_settings={
1295)         'help_option_names': ['-h', '--help'],
1296)         'ignore_unknown_options': True,
1297)         'allow_interspersed_args': False,
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1298)     },
1299)     invoke_without_command=True,
1300)     cls=_DefaultToVaultGroup,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1301)     help=(
1302)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_EXPORT_01),
1303)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_EXPORT_02),
1304)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_EXPORT_03),
1305)     ),
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 1 week ago

1307) @version_option
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1308) @color_forcing_pseudo_option
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 3 months ago

1312)     """Export a foreign configuration to standard output.
1313) 
1314)     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

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 month ago

1325)         deprecation.warning(
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1326)             _msg.TranslatedString(
1327)                 _msg.WarnMsgTemplate.V10_SUBCOMMAND_REQUIRED
1328)             ),
1329)             extra={'color': ctx.color},
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1330)         )
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1331)         # See definition of click.Group.invoke, non-chained case.
1332)         with ctx:
1333)             sub_ctx = derivepassphrase_export_vault.make_context(
1334)                 'vault', ctx.args, parent=ctx
1335)             )
1336)             # Constructing the subcontext above will usually already
1337)             # lead to a click.UsageError, so this block typically won't
1338)             # actually be called.
1339)             with sub_ctx:  # pragma: no cover
1340)                 return derivepassphrase_export_vault.invoke(sub_ctx)
1341)     return None
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1342) 
1343) 
1344) def _load_data(
1345)     fmt: Literal['v0.2', 'v0.3', 'storeroom'],
1346)     path: str | bytes | os.PathLike[str],
1347)     key: bytes,
1348) ) -> Any:  # noqa: ANN401
1349)     contents: bytes
1350)     module: types.ModuleType
Marco Ricci Add support for Python 3.9

Marco Ricci authored 3 months ago

1351)     # Use match/case here once Python 3.9 becomes unsupported.
1352)     if fmt == 'v0.2':
1353)         module = importlib.import_module(
1354)             'derivepassphrase.exporter.vault_native'
1355)         )
1356)         if module.STUBBED:
1357)             raise ModuleNotFoundError
1358)         with open(path, 'rb') as infile:
1359)             contents = base64.standard_b64decode(infile.read())
1360)         return module.export_vault_native_data(
1361)             contents, key, try_formats=['v0.2']
1362)         )
1363)     elif fmt == 'v0.3':  # noqa: RET505
1364)         module = importlib.import_module(
1365)             'derivepassphrase.exporter.vault_native'
1366)         )
1367)         if module.STUBBED:
1368)             raise ModuleNotFoundError
1369)         with open(path, 'rb') as infile:
1370)             contents = base64.standard_b64decode(infile.read())
1371)         return module.export_vault_native_data(
1372)             contents, key, try_formats=['v0.3']
1373)         )
1374)     elif fmt == 'storeroom':
1375)         module = importlib.import_module('derivepassphrase.exporter.storeroom')
1376)         if module.STUBBED:
1377)             raise ModuleNotFoundError
1378)         return module.export_storeroom_data(path, key)
1379)     else:  # pragma: no cover
1380)         assert_never(fmt)
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1381) 
1382) 
Marco Ricci Add shell completion suppor...

Marco Ricci authored 1 week ago

1383) def _shell_complete_vault_path(  # pragma: no cover
1384)     ctx: click.Context,
1385)     param: click.Parameter,
1386)     incomplete: str,
1387) ) -> list[str | click.shell_completion.CompletionItem]:
1388)     del ctx, param
1389)     if incomplete and 'VAULT_PATH'.startswith(incomplete):
1390)         ret: set[str | click.shell_completion.CompletionItem] = {'VAULT_PATH'}
1391)         for f in os.listdir():
1392)             if f.startswith(incomplete):
1393)                 ret.add(f + os.path.sep if os.path.isdir(f) else f)
1394)         return sorted(ret)
1395)     return [
1396)         click.shell_completion.CompletionItem('', type='file'),
1397)     ]
1398) 
1399) 
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

1400) @derivepassphrase_export.command(
1401)     'vault',
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 1 week ago

1403)     cls=CommandWithHelpGroups,
1404)     help=(
1405)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_EXPORT_VAULT_01),
1406)         _msg.TranslatedString(
1407)             _msg.Label.DERIVEPASSPHRASE_EXPORT_VAULT_02,
1408)             path_metavar=_msg.TranslatedString(
1409)                 _msg.Label.EXPORT_VAULT_METAVAR_PATH,
1410)             ),
1411)         ),
1412)         _msg.TranslatedString(
1413)             _msg.Label.DERIVEPASSPHRASE_EXPORT_VAULT_03,
1414)             path_metavar=_msg.TranslatedString(
1415)                 _msg.Label.EXPORT_VAULT_METAVAR_PATH,
1416)             ),
1417)         ),
1418)     ),
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1419) )
1420) @click.option(
1421)     '-f',
1422)     '--format',
1423)     'formats',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 1 week ago

1428)     help=_msg.TranslatedString(
1429)         _msg.Label.EXPORT_VAULT_FORMAT_HELP_TEXT,
1430)         defaults_hint=_msg.TranslatedString(
1431)             _msg.Label.EXPORT_VAULT_FORMAT_DEFAULTS_HELP_TEXT,
1432)         ),
1433)         metavar=_msg.TranslatedString(
1434)             _msg.Label.EXPORT_VAULT_FORMAT_METAVAR_FMT,
1435)         ),
1436)     ),
1437)     cls=StandardOption,
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1438) )
1439) @click.option(
1440)     '-k',
1441)     '--key',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

1442)     metavar=_msg.TranslatedString(_msg.Label.EXPORT_VAULT_KEY_METAVAR_K),
1443)     help=_msg.TranslatedString(
1444)         _msg.Label.EXPORT_VAULT_KEY_HELP_TEXT,
1445)         metavar=_msg.TranslatedString(_msg.Label.EXPORT_VAULT_KEY_METAVAR_K),
1446)         defaults_hint=_msg.TranslatedString(
1447)             _msg.Label.EXPORT_VAULT_KEY_DEFAULTS_HELP_TEXT,
1448)         ),
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 1 week ago

1450)     cls=StandardOption,
1451) )
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

1452) @version_option
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1453) @color_forcing_pseudo_option
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 week ago

1455) @click.argument(
1456)     'path',
1457)     metavar=_msg.TranslatedString(_msg.Label.EXPORT_VAULT_METAVAR_PATH),
1458)     required=True,
Marco Ricci Add shell completion suppor...

Marco Ricci authored 1 week ago

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

Marco Ricci authored 3 months ago

1460) )
1461) @click.pass_context
1462) def derivepassphrase_export_vault(
1463)     ctx: click.Context,
1464)     /,
1465)     *,
1466)     path: str | bytes | os.PathLike[str],
1467)     formats: Sequence[Literal['v0.2', 'v0.3', 'storeroom']] = (),
1468)     key: str | bytes | None = None,
1469) ) -> None:
1470)     """Export a vault-native configuration to standard output.
1471) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 3 months ago

1479) 
1480)     """
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 3 months ago

1482)     if path in {'VAULT_PATH', b'VAULT_PATH'}:
1483)         path = exporter.get_vault_path()
1484)     if key is None:
1485)         key = exporter.get_vault_key()
1486)     elif isinstance(key, str):  # pragma: no branch
1487)         key = key.encode('utf-8')
1488)     for fmt in formats:
1489)         try:
1490)             config = _load_data(fmt, path, key)
1491)         except (
1492)             IsADirectoryError,
1493)             NotADirectoryError,
1494)             ValueError,
1495)             RuntimeError,
1496)         ):
Marco Ricci Replace strings in `derivep...

Marco Ricci authored 1 week ago

1497)             logger.info(
1498)                 _msg.TranslatedString(
1499)                     _msg.InfoMsgTemplate.CANNOT_LOAD_AS_VAULT_CONFIG,
1500)                     path=path,
1501)                     fmt=fmt,
1502)                 ),
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1503)                 extra={'color': ctx.color},
Marco Ricci Replace strings in `derivep...

Marco Ricci authored 1 week ago

1504)             )
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

1508)                 _msg.TranslatedString(
1509)                     _msg.ErrMsgTemplate.CANNOT_PARSE_AS_VAULT_CONFIG_OSERROR,
1510)                     path=path,
1511)                     error=exc.strerror,
1512)                     filename=exc.filename,
1513)                 ).maybe_without_filename(),
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1514)                 extra={'color': ctx.color},
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1515)             )
1516)             ctx.exit(1)
1517)         except ModuleNotFoundError:
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

1519)                 _msg.TranslatedString(
1520)                     _msg.ErrMsgTemplate.MISSING_MODULE,
1521)                     module='cryptography',
1522)                 ),
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1523)                 extra={'color': ctx.color},
Marco Ricci Replace strings in `derivep...

Marco Ricci authored 1 week ago

1524)             )
1525)             logger.info(
1526)                 _msg.TranslatedString(
1527)                     _msg.InfoMsgTemplate.PIP_INSTALL_EXTRA,
1528)                     extra_name='export',
1529)                 ),
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1530)                 extra={'color': ctx.color},
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

1531)             )
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1532)             ctx.exit(1)
1533)         else:
1534)             if not _types.is_vault_config(config):
Marco Ricci Replace strings in `derivep...

Marco Ricci authored 1 week ago

1535)                 logger.error(
1536)                     _msg.TranslatedString(
1537)                         _msg.ErrMsgTemplate.INVALID_VAULT_CONFIG,
1538)                         config=config,
1539)                     ),
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1540)                     extra={'color': ctx.color},
Marco Ricci Replace strings in `derivep...

Marco Ricci authored 1 week ago

1541)                 )
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1542)                 ctx.exit(1)
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1543)             click.echo(
1544)                 json.dumps(config, indent=2, sort_keys=True),
1545)                 color=ctx.color,
1546)             )
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1547)             break
1548)     else:
Marco Ricci Replace strings in `derivep...

Marco Ricci authored 1 week ago

1549)         logger.error(
1550)             _msg.TranslatedString(
1551)                 _msg.ErrMsgTemplate.CANNOT_PARSE_AS_VAULT_CONFIG,
1552)                 path=path,
1553)             ).maybe_without_filename(),
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1554)             extra={'color': ctx.color},
Marco Ricci Replace strings in `derivep...

Marco Ricci authored 1 week ago

1555)         )
Marco Ricci Reintegrate all functionali...

Marco Ricci authored 3 months ago

1556)         ctx.exit(1)
1557) 
1558) 
1559) # Vault
1560) # =====
1561) 
1562) 
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 3 months ago

1565) ) -> str | bytes | pathlib.Path:
1566)     """Return the filename of the configuration file for the subsystem.
1567) 
1568)     The (implicit default) file is currently named `settings.json`,
1569)     located within the configuration directory as determined by the
1570)     `DERIVEPASSPHRASE_PATH` environment variable, or by
1571)     [`click.get_app_dir`][] in POSIX mode.  Depending on the requested
1572)     subsystem, this will usually be a different file within that
1573)     directory.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

1574) 
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

1575)     Args:
1576)         subsystem:
1577)             Name of the configuration subsystem whose configuration
1578)             filename to return.  If not given, return the old filename
1579)             from before the subcommand migration.  If `None`, return the
1580)             configuration directory instead.
1581) 
1582)     Raises:
1583)         AssertionError:
1584)             An unknown subsystem was passed.
1585) 
1586)     Deprecated:
1587)         Since v0.2.0: The implicit default subsystem and the old
1588)         configuration filename are deprecated, and will be removed in v1.0.
1589)         The subsystem will be mandatory to specify.
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

1590) 
1591)     """
1592)     path: str | bytes | pathlib.Path
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 6 months ago

1609) 
1610) 
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 6 months ago

1616) 
1617)     Returns:
Marco Ricci Generate nicer documentatio...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 6 months ago

1619) 
1620)     Raises:
1621)         OSError:
1622)             There was an OS error accessing the file.
1623)         ValueError:
1624)             The data loaded from the file is not a vault(1)-compatible
1625)             config.
1626) 
1627)     """
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

1633)     return data
1634) 
1635) 
Marco Ricci Permit one flaky test and f...

Marco Ricci authored 3 months ago

1636) def _migrate_and_load_old_config() -> tuple[
1637)     _types.VaultConfig, OSError | None
1638) ]:
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 3 months ago

1644) 
1645)     Returns:
1646)         The vault settings, and an optional exception encountered during
Marco Ricci Generate nicer documentatio...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 3 months ago

1649) 
1650)     Raises:
1651)         OSError:
1652)             There was an OS error accessing the old file.
1653)         ValueError:
1654)             The data loaded from the file is not a vault(1)-compatible
1655)             config.
1656) 
1657)     """
1658)     new_filename = _config_filename(subsystem='vault')
Marco Ricci Make obtaining the compatib...

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 3 months ago

1660)     with open(old_filename, 'rb') as fileobj:
1661)         data = json.load(fileobj)
1662)     if not _types.is_vault_config(data):
1663)         raise ValueError(_INVALID_VAULT_CONFIG)
1664)     try:
1665)         os.replace(old_filename, new_filename)
1666)     except OSError as exc:
1667)         return data, exc
1668)     else:
1669)         return data, None
1670) 
1671) 
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 5 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

1674) 
Marco Ricci Generate nicer documentatio...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 6 months ago

1677) 
1678)     Args:
1679)         config:
1680)             vault configuration to save.
1681) 
1682)     Raises:
1683)         OSError:
1684)             There was an OS error accessing or writing the file.
1685)         ValueError:
1686)             The data cannot be stored as a vault(1)-compatible config.
1687) 
1688)     """
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 5 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 5 months ago

1692)     filedir = os.path.dirname(os.path.abspath(filename))
1693)     try:
1694)         os.makedirs(filedir, exist_ok=False)
1695)     except FileExistsError:
1696)         if not os.path.isdir(filedir):
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

1699)         json.dump(config, fileobj)
1700) 
1701) 
Marco Ricci Introduce a central user co...

Marco Ricci authored 3 weeks ago

1702) def _load_user_config() -> dict[str, Any]:
1703)     """Load the user config from the application directory.
1704) 
1705)     The filename is obtained via [`_config_filename`][].
1706) 
1707)     Returns:
1708)         The user configuration, as a nested `dict`.
1709) 
1710)     Raises:
1711)         OSError:
1712)             There was an OS error accessing the file.
1713)         ValueError:
1714)             The data loaded from the file is not a valid configuration
1715)             file.
1716) 
1717)     """
1718)     filename = _config_filename(subsystem='user configuration')
1719)     with open(filename, 'rb') as fileobj:
1720)         return tomllib.load(fileobj)
1721) 
1722) 
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 6 months ago

1730) 
1731)     Args:
1732)         conn:
Marco Ricci Support one-off SSH agent c...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 6 months ago

1735) 
1736)     Yields:
Marco Ricci Convert old syntax for Yiel...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 6 months ago

1739) 
1740)     Raises:
Marco Ricci Document and handle other e...

Marco Ricci authored 4 months ago

1741)         KeyError:
1742)             `conn` was `None`, and the `SSH_AUTH_SOCK` environment
1743)             variable was not found.
Marco Ricci Fail gracefully if UNIX dom...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

1758) 
1759)     """
Marco Ricci Support one-off SSH agent c...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 month ago

1765)         suitable_keys = copy.copy(all_key_comment_pairs)
1766)         for pair in all_key_comment_pairs:
1767)             key, _comment = pair
1768)             if vault.Vault.is_suitable_ssh_key(key, client=client):
1769)                 yield pair
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 6 months ago

1772) 
1773) 
1774) def _prompt_for_selection(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

1777)     single_choice_prompt: str = 'Confirm this choice?',
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1778)     ctx: click.Context | None = None,
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1779) ) -> int:
1780)     """Prompt user for a choice among the given items.
1781) 
1782)     Print the heading, if any, then present the items to the user.  If
1783)     there are multiple items, prompt the user for a selection, validate
1784)     the choice, then return the list index of the selected item.  If
1785)     there is only a single item, request confirmation for that item
1786)     instead, and return the correct index.
1787) 
1788)     Args:
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

1791)         heading:
1792)             A heading for the list of items, to print immediately
1793)             before.  Defaults to a reasonable standard heading.  If
1794)             explicitly empty, print no heading.
1795)         single_choice_prompt:
1796)             The confirmation prompt if there is only a single possible
1797)             choice.  Defaults to a reasonable standard prompt.
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1798)         ctx:
1799)             An optional `click` context, from which output device
1800)             properties and color preferences will be queried.
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1801) 
1802)     Returns:
1803)         An index into the items sequence, indicating the user's
1804)         selection.
1805) 
1806)     Raises:
1807)         IndexError:
1808)             The user made an invalid or empty selection, or requested an
1809)             abort.
1810) 
1811)     """
1812)     n = len(items)
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1813)     color = ctx.color if ctx is not None else None
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1814)     if heading:
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1815)         click.echo(click.style(heading, bold=True), color=color)
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1816)     for i, x in enumerate(items, start=1):
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1817)         click.echo(click.style(f'[{i}]', bold=True), nl=False, color=color)
1818)         click.echo(' ', nl=False, color=color)
1819)         click.echo(x, color=color)
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1820)     if n > 1:
1821)         choices = click.Choice([''] + [str(i) for i in range(1, n + 1)])
1822)         choice = click.prompt(
1823)             f'Your selection? (1-{n}, leave empty to abort)',
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

1824)             err=True,
1825)             type=choices,
1826)             show_choices=False,
1827)             show_default=False,
1828)             default='',
1829)         )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 5 months ago

1833)     prompt_suffix = (
1834)         ' ' if single_choice_prompt.endswith(tuple('?.!')) else ': '
1835)     )
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

1836)     try:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

1837)         click.confirm(
1838)             single_choice_prompt,
1839)             prompt_suffix=prompt_suffix,
1840)             err=True,
1841)             abort=True,
1842)             default=False,
1843)             show_default=False,
1844)         )
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 5 months ago

1845)     except click.Abort:
1846)         raise IndexError(_EMPTY_SELECTION) from None
1847)     return 0
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1848) 
1849) 
1850) def _select_ssh_key(
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1851)     conn: ssh_agent.SSHAgentClient | socket.socket | None = None,
1852)     /,
1853)     *,
1854)     ctx: click.Context | None = None,
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 6 months ago

1861) 
1862)     Args:
1863)         conn:
Marco Ricci Support one-off SSH agent c...

Marco Ricci authored 1 month ago

1864)             An optional connection hint to the SSH agent.  See
1865)             [`ssh_agent.SSHAgentClient.ensure_agent_subcontext`][].
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1866)         ctx:
1867)             An `click` context, queried for output device properties and
1868)             color preferences when issuing the prompt.
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

1869) 
1870)     Returns:
1871)         The selected SSH key.
1872) 
1873)     Raises:
Marco Ricci Document and handle other e...

Marco Ricci authored 4 months ago

1874)         KeyError:
1875)             `conn` was `None`, and the `SSH_AUTH_SOCK` environment
1876)             variable was not found.
Marco Ricci Fail gracefully if UNIX dom...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

1884)         IndexError:
1885)             The user made an invalid or empty selection, or requested an
1886)             abort.
Marco Ricci Distinguish between a key l...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

1894)     """
1895)     suitable_keys = list(_get_suitable_ssh_keys(conn))
1896)     key_listing: list[str] = []
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 1 month ago

1901)         remaining_key_display_length = KEY_DISPLAY_LENGTH - 1 - len(keytype)
1902)         key_extract = min(
1903)             key_str,
1904)             '...' + key_str[-remaining_key_display_length:],
1905)             key=len,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 5 months ago

1910)         key_listing,
1911)         heading='Suitable SSH keys:',
1912)         single_choice_prompt='Use this key?',
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1913)         ctx=ctx,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

1915)     return suitable_keys[choice].key
1916) 
1917) 
1918) def _prompt_for_passphrase() -> str:
1919)     """Interactively prompt for the passphrase.
1920) 
1921)     Calls [`click.prompt`][] internally.  Moved into a separate function
1922)     mainly for testing/mocking purposes.
1923) 
1924)     Returns:
1925)         The user input.
1926) 
1927)     """
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 5 months ago

1928)     return cast(
1929)         str,
1930)         click.prompt(
1931)             'Passphrase',
1932)             default='',
1933)             hide_input=True,
1934)             show_default=False,
1935)             err=True,
1936)         ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

1938) 
1939) 
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 2 weeks ago

1942) 
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

1943)     def escape(string: str) -> str:
1944)         translated = string.translate({
1945)             0: r'\u0000',
1946)             1: r'\u0001',
1947)             2: r'\u0002',
1948)             3: r'\u0003',
1949)             4: r'\u0004',
1950)             5: r'\u0005',
1951)             6: r'\u0006',
1952)             7: r'\u0007',
1953)             8: r'\b',
1954)             9: r'\t',
1955)             10: r'\n',
1956)             11: r'\u000B',
1957)             12: r'\f',
1958)             13: r'\r',
1959)             14: r'\u000E',
1960)             15: r'\u000F',
1961)             ord('"'): r'\"',
1962)             ord('\\'): r'\\',
1963)             127: r'\u007F',
1964)         })
1965)         return f'"{translated}"' if translated != string else string
Marco Ricci Fix formatting, some covera...

Marco Ricci authored 2 weeks ago

1966) 
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

1967)     return '.'.join(map(escape, parts))
1968) 
1969) 
Marco Ricci Signal and list falsy value...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 3 months ago

1972) 
1973) 
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 weeks ago

1978)     main_config: dict[str, Any],
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

1979)     ctx: click.Context | None = None,
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 weeks ago

1981)     form_key = 'unicode-normalization-form'
1982)     default_form: str = main_config.get('vault', {}).get(
1983)         f'default-{form_key}', 'NFC'
1984)     )
1985)     form_dict: dict[str, dict] = main_config.get('vault', {}).get(form_key, {})
1986)     form: Any = (
1987)         default_form
1988)         if isinstance(key, _ORIGIN) or key == ('global',)
1989)         else form_dict.get(key[1], default_form)
1990)     )
1991)     config_key = (
1992)         _toml_key('vault', key[1], form_key)
1993)         if isinstance(key, tuple) and len(key) > 1 and key[1] in form_dict
1994)         else f'vault.default-{form_key}'
1995)     )
1996)     if form not in {'NFC', 'NFD', 'NFKC', 'NFKD'}:
1997)         msg = f'Invalid value {form!r} for config key {config_key}'
1998)         raise AssertionError(msg)
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 3 weeks ago

2000)     formatted_key = (
2001)         key.value if isinstance(key, _ORIGIN) else _types.json_path(key)
2002)     )
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 1 month ago

2014)                 formatted_key,
2015)                 form,
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

2016)                 stacklevel=2,
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

2017)                 extra={'color': ctx.color if ctx is not None else None},
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

2018)             )
2019) 
2020) 
Marco Ricci Hoist and add tests for int...

Marco Ricci authored 3 weeks ago

2021) def _key_to_phrase(
2022)     key_: str | bytes | bytearray,
2023)     /,
2024)     *,
2025)     error_callback: Callable[..., NoReturn] = sys.exit,
2026) ) -> bytes | bytearray:
2027)     key = base64.standard_b64decode(key_)
2028)     try:
2029)         with ssh_agent.SSHAgentClient.ensure_agent_subcontext() as client:
2030)             try:
2031)                 return vault.Vault.phrase_from_key(key, conn=client)
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 3 weeks ago

2033)                 try:
2034)                     keylist = client.list_keys()
2035)                 except ssh_agent.SSHAgentFailedError:
2036)                     pass
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 3 weeks ago

2039)                 else:
2040)                     if not any(  # pragma: no branch
2041)                         k == key for k, _ in keylist
2042)                     ):
2043)                         error_callback(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2044)                             _msg.TranslatedString(
2045)                                 _msg.ErrMsgTemplate.SSH_KEY_NOT_LOADED
2046)                             )
Marco Ricci Hoist and add tests for int...

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 1 week ago

2048)                 error_callback(
2049)                     _msg.TranslatedString(
2050)                         _msg.ErrMsgTemplate.AGENT_REFUSED_SIGNATURE
2051)                     ),
2052)                     exc_info=exc,
2053)                 )
Marco Ricci Hoist and add tests for int...

Marco Ricci authored 3 weeks ago

2054)     except KeyError:
2055)         error_callback(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

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

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

2061)         error_callback(
2062)             _msg.TranslatedString(
2063)                 _msg.ErrMsgTemplate.CANNOT_CONNECT_TO_AGENT,
2064)                 error=exc.strerror,
2065)                 filename=exc.filename,
2066)             ).maybe_without_filename()
2067)         )
2068)     except RuntimeError as exc:
2069)         error_callback(
2070)             _msg.TranslatedString(_msg.ErrMsgTemplate.CANNOT_UNDERSTAND_AGENT),
2071)             exc_info=exc,
2072)         )
Marco Ricci Hoist and add tests for int...

Marco Ricci authored 3 weeks ago

2073) 
2074) 
Marco Ricci Support exporting the `vaul...

Marco Ricci authored 2 weeks ago

2075) def _print_config_as_sh_script(
2076)     config: _types.VaultConfig,
2077)     /,
2078)     *,
2079)     outfile: TextIO,
2080)     prog_name_list: Sequence[str],
2081) ) -> None:
2082)     service_keys = (
2083)         'length',
2084)         'repeat',
2085)         'lower',
2086)         'upper',
2087)         'number',
2088)         'space',
2089)         'dash',
2090)         'symbol',
2091)     )
2092)     print('#!/bin/sh -e', file=outfile)
2093)     print(file=outfile)
2094)     print(shlex.join([*prog_name_list, '--clear']), file=outfile)
2095)     sv_obj_pairs: list[
2096)         tuple[
2097)             str | None,
2098)             _types.VaultConfigGlobalSettings
2099)             | _types.VaultConfigServicesSettings,
2100)         ],
2101)     ] = list(config['services'].items())
2102)     if config.get('global', {}):
2103)         sv_obj_pairs.insert(0, (None, config['global']))
2104)     for sv, sv_obj in sv_obj_pairs:
2105)         this_service_keys = tuple(k for k in service_keys if k in sv_obj)
2106)         this_other_keys = tuple(k for k in sv_obj if k not in service_keys)
2107)         if this_other_keys:
2108)             other_sv_obj = {k: sv_obj[k] for k in this_other_keys}  # type: ignore[literal-required]
2109)             dumped_config = json.dumps(
2110)                 (
2111)                     {'services': {sv: other_sv_obj}}
2112)                     if sv is not None
2113)                     else {'global': other_sv_obj, 'services': {}}
2114)                 ),
2115)                 ensure_ascii=False,
2116)                 indent=None,
2117)             )
2118)             print(
2119)                 shlex.join([*prog_name_list, '--import', '-']) + " <<'HERE'",
2120)                 dumped_config,
2121)                 'HERE',
2122)                 sep='\n',
2123)                 file=outfile,
2124)             )
2125)         if not this_service_keys and not this_other_keys and sv:
2126)             dumped_config = json.dumps(
2127)                 {'services': {sv: {}}},
2128)                 ensure_ascii=False,
2129)                 indent=None,
2130)             )
2131)             print(
2132)                 shlex.join([*prog_name_list, '--import', '-']) + " <<'HERE'",
2133)                 dumped_config,
2134)                 'HERE',
2135)                 sep='\n',
2136)                 file=outfile,
2137)             )
2138)         elif this_service_keys:
2139)             tokens = [*prog_name_list, '--config']
2140)             for key in this_service_keys:
2141)                 tokens.extend([f'--{key}', str(sv_obj[key])])  # type: ignore[literal-required]
2142)             if sv is not None:
2143)                 tokens.extend(['--', sv])
2144)             print(shlex.join(tokens), file=outfile)
2145) 
2146) 
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

2151)     option_group_name = _msg.TranslatedString(
2152)         _msg.Label.PASSPHRASE_GENERATION_LABEL
2153)     )
2154)     epilog = _msg.TranslatedString(
2155)         _msg.Label.PASSPHRASE_GENERATION_EPILOG,
2156)         metavar=_msg.TranslatedString(
2157)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2158)         ),
2159)     )
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

2161) 
2162) class ConfigurationOption(OptionGroupOption):
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

2168) 
2169) class StorageManagementOption(OptionGroupOption):
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

2172)     option_group_name = _msg.TranslatedString(
2173)         _msg.Label.STORAGE_MANAGEMENT_LABEL
2174)     )
2175)     epilog = _msg.TranslatedString(
2176)         _msg.Label.STORAGE_MANAGEMENT_EPILOG,
2177)         metavar=_msg.TranslatedString(
2178)             _msg.Label.STORAGE_MANAGEMENT_METAVAR_PATH
2179)         ),
2180)     )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 4 weeks ago

2183) class CompatibilityOption(OptionGroupOption):
2184)     """Compatibility and incompatibility options for the CLI."""
2185) 
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2186)     option_group_name = _msg.TranslatedString(
2187)         _msg.Label.COMPATIBILITY_OPTION_LABEL
2188)     )
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

2189) 
2190) 
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2191) def _validate_occurrence_constraint(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 4 months ago

2196)     """Check that the occurrence constraint is valid (int, 0 or larger).
2197) 
2198)     Args:
2199)         ctx: The `click` context.
2200)         param: The current command-line parameter.
2201)         value: The parameter value to be checked.
2202) 
2203)     Returns:
2204)         The parsed parameter value.
2205) 
2206)     Raises:
2207)         click.BadParameter: The parameter value is invalid.
2208) 
2209)     """
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

2212)     if value is None:
2213)         return value
2214)     if isinstance(value, int):
2215)         int_value = value
2216)     else:
2217)         try:
2218)             int_value = int(value, 10)
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 6 months ago

2223)     return int_value
2224) 
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2225) 
2226) def _validate_length(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 4 months ago

2231)     """Check that the length is valid (int, 1 or larger).
2232) 
2233)     Args:
2234)         ctx: The `click` context.
2235)         param: The current command-line parameter.
2236)         value: The parameter value to be checked.
2237) 
2238)     Returns:
2239)         The parsed parameter value.
2240) 
2241)     Raises:
2242)         click.BadParameter: The parameter value is invalid.
2243) 
2244)     """
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

2247)     if value is None:
2248)         return value
2249)     if isinstance(value, int):
2250)         int_value = value
2251)     else:
2252)         try:
2253)             int_value = int(value, 10)
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 6 months ago

2258)     return int_value
2259) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2260) 
Marco Ricci Add shell completion suppor...

Marco Ricci authored 1 week ago

2261) def _shell_complete_path(  # pragma: no cover
2262)     ctx: click.Context,
2263)     parameter: click.Parameter,
2264)     incomplete: str,
2265) ) -> list[str | click.shell_completion.CompletionItem]:
2266)     del ctx, parameter, incomplete
2267)     return [click.shell_completion.CompletionItem('', type='file')]
2268) 
2269) 
2270) def _shell_complete_service(  # pragma: no cover
2271)     ctx: click.Context,
2272)     parameter: click.Parameter,
2273)     incomplete: str,
2274) ) -> list[str | click.shell_completion.CompletionItem]:
2275)     del ctx, parameter
2276)     try:
2277)         config = _load_config()
2278)         return [sv for sv in config['services'] if sv.startswith(incomplete)]
2279)     except FileNotFoundError:
2280)         try:
2281)             config, _exc = _migrate_and_load_old_config()
2282)             return [
2283)                 sv for sv in config['services'] if sv.startswith(incomplete)
2284)             ]
2285)         except FileNotFoundError:
2286)             return []
2287)     except Exception:  # noqa: BLE001
2288)         return []
2289) 
2290) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

2292) # Enter notes below the line with the cut mark (ASCII scissors and
2293) # dashes).  Lines above the cut mark (such as this one) will be ignored.
2294) #
2295) # If you wish to clear the notes, leave everything beyond the cut mark
2296) # blank.  However, if you leave the *entire* file blank, also removing
2297) # the cut mark, then the edit is aborted, and the old notes contents are
2298) # retained.
2299) #
2300) # - - - - - >8 - - - - - >8 - - - - - >8 - - - - - >8 - - - - -
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

2302) DEFAULT_NOTES_MARKER = '# - - - - - >8 - - - - -'
2303) 
2304) 
Marco Ricci Reimplement deprecated subc...

Marco Ricci authored 1 month ago

2305) @derivepassphrase.command(
2306)     'vault',
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 1 week ago

2309)     help=(
2310)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_VAULT_01),
2311)         _msg.TranslatedString(
2312)             _msg.Label.DERIVEPASSPHRASE_VAULT_02,
2313)             service_metavar=_msg.TranslatedString(
2314)                 _msg.Label.VAULT_METAVAR_SERVICE
2315)             ),
2316)         ),
2317)     ),
2318)     epilog=(
2319)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_VAULT_EPILOG_01),
2320)         _msg.TranslatedString(_msg.Label.DERIVEPASSPHRASE_VAULT_EPILOG_02),
2321)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2322) )
2323) @click.option(
2324)     '-p',
2325)     '--phrase',
2326)     'use_phrase',
2327)     is_flag=True,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2328)     help=_msg.TranslatedString(
2329)         _msg.Label.DERIVEPASSPHRASE_VAULT_PHRASE_HELP_TEXT
2330)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 5 months ago

2332) )
2333) @click.option(
2334)     '-k',
2335)     '--key',
2336)     'use_key',
2337)     is_flag=True,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2338)     help=_msg.TranslatedString(
2339)         _msg.Label.DERIVEPASSPHRASE_VAULT_KEY_HELP_TEXT
2340)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 5 months ago

2342) )
2343) @click.option(
2344)     '-l',
2345)     '--length',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2346)     metavar=_msg.TranslatedString(
2347)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2348)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

2350)     help=_msg.TranslatedString(
2351)         _msg.Label.DERIVEPASSPHRASE_VAULT_LENGTH_HELP_TEXT,
2352)         metavar=_msg.TranslatedString(
2353)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2354)         ),
2355)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 5 months ago

2357) )
2358) @click.option(
2359)     '-r',
2360)     '--repeat',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2361)     metavar=_msg.TranslatedString(
2362)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2363)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

2365)     help=_msg.TranslatedString(
2366)         _msg.Label.DERIVEPASSPHRASE_VAULT_REPEAT_HELP_TEXT,
2367)         metavar=_msg.TranslatedString(
2368)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2369)         ),
2370)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 5 months ago

2372) )
2373) @click.option(
2374)     '--lower',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2375)     metavar=_msg.TranslatedString(
2376)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2377)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

2379)     help=_msg.TranslatedString(
2380)         _msg.Label.DERIVEPASSPHRASE_VAULT_LOWER_HELP_TEXT,
2381)         metavar=_msg.TranslatedString(
2382)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2383)         ),
2384)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 5 months ago

2386) )
2387) @click.option(
2388)     '--upper',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2389)     metavar=_msg.TranslatedString(
2390)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2391)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

2393)     help=_msg.TranslatedString(
2394)         _msg.Label.DERIVEPASSPHRASE_VAULT_UPPER_HELP_TEXT,
2395)         metavar=_msg.TranslatedString(
2396)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2397)         ),
2398)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 5 months ago

2400) )
2401) @click.option(
2402)     '--number',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2403)     metavar=_msg.TranslatedString(
2404)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2405)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

2407)     help=_msg.TranslatedString(
2408)         _msg.Label.DERIVEPASSPHRASE_VAULT_NUMBER_HELP_TEXT,
2409)         metavar=_msg.TranslatedString(
2410)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2411)         ),
2412)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 5 months ago

2414) )
2415) @click.option(
2416)     '--space',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2417)     metavar=_msg.TranslatedString(
2418)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2419)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

2421)     help=_msg.TranslatedString(
2422)         _msg.Label.DERIVEPASSPHRASE_VAULT_SPACE_HELP_TEXT,
2423)         metavar=_msg.TranslatedString(
2424)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2425)         ),
2426)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 5 months ago

2428) )
2429) @click.option(
2430)     '--dash',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2431)     metavar=_msg.TranslatedString(
2432)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2433)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

2435)     help=_msg.TranslatedString(
2436)         _msg.Label.DERIVEPASSPHRASE_VAULT_DASH_HELP_TEXT,
2437)         metavar=_msg.TranslatedString(
2438)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2439)         ),
2440)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 5 months ago

2442) )
2443) @click.option(
2444)     '--symbol',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2445)     metavar=_msg.TranslatedString(
2446)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2447)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

2449)     help=_msg.TranslatedString(
2450)         _msg.Label.DERIVEPASSPHRASE_VAULT_SYMBOL_HELP_TEXT,
2451)         metavar=_msg.TranslatedString(
2452)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2453)         ),
2454)     ),
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 5 months ago

2456) )
2457) @click.option(
2458)     '-n',
2459)     '--notes',
2460)     'edit_notes',
2461)     is_flag=True,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2462)     help=_msg.TranslatedString(
2463)         _msg.Label.DERIVEPASSPHRASE_VAULT_NOTES_HELP_TEXT,
2464)         service_metavar=_msg.TranslatedString(
2465)             _msg.Label.VAULT_METAVAR_SERVICE
2466)         ),
2467)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2468)     cls=ConfigurationOption,
2469) )
2470) @click.option(
2471)     '-c',
2472)     '--config',
2473)     'store_config_only',
2474)     is_flag=True,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2475)     help=_msg.TranslatedString(
2476)         _msg.Label.DERIVEPASSPHRASE_VAULT_CONFIG_HELP_TEXT,
2477)         service_metavar=_msg.TranslatedString(
2478)             _msg.Label.VAULT_METAVAR_SERVICE
2479)         ),
2480)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2481)     cls=ConfigurationOption,
2482) )
2483) @click.option(
2484)     '-x',
2485)     '--delete',
2486)     'delete_service_settings',
2487)     is_flag=True,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2488)     help=_msg.TranslatedString(
2489)         _msg.Label.DERIVEPASSPHRASE_VAULT_DELETE_HELP_TEXT,
2490)         service_metavar=_msg.TranslatedString(
2491)             _msg.Label.VAULT_METAVAR_SERVICE
2492)         ),
2493)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2494)     cls=ConfigurationOption,
2495) )
2496) @click.option(
2497)     '--delete-globals',
2498)     is_flag=True,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2499)     help=_msg.TranslatedString(
2500)         _msg.Label.DERIVEPASSPHRASE_VAULT_DELETE_GLOBALS_HELP_TEXT,
2501)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2502)     cls=ConfigurationOption,
2503) )
2504) @click.option(
2505)     '-X',
2506)     '--clear',
2507)     'clear_all_settings',
2508)     is_flag=True,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2509)     help=_msg.TranslatedString(
2510)         _msg.Label.DERIVEPASSPHRASE_VAULT_DELETE_ALL_HELP_TEXT,
2511)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2512)     cls=ConfigurationOption,
2513) )
2514) @click.option(
2515)     '-e',
2516)     '--export',
2517)     'export_settings',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2518)     metavar=_msg.TranslatedString(
2519)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2520)     ),
2521)     help=_msg.TranslatedString(
2522)         _msg.Label.DERIVEPASSPHRASE_VAULT_EXPORT_HELP_TEXT,
2523)         metavar=_msg.TranslatedString(
2524)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2525)         ),
2526)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 5 months ago

2529) )
2530) @click.option(
2531)     '-i',
2532)     '--import',
2533)     'import_settings',
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2534)     metavar=_msg.TranslatedString(
2535)         _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2536)     ),
2537)     help=_msg.TranslatedString(
2538)         _msg.Label.DERIVEPASSPHRASE_VAULT_IMPORT_HELP_TEXT,
2539)         metavar=_msg.TranslatedString(
2540)             _msg.Label.PASSPHRASE_GENERATION_METAVAR_NUMBER
2541)         ),
2542)     ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 4 weeks ago

2546) @click.option(
2547)     '--overwrite-existing/--merge-existing',
2548)     'overwrite_config',
2549)     default=False,
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2550)     help=_msg.TranslatedString(
2551)         _msg.Label.DERIVEPASSPHRASE_VAULT_OVERWRITE_HELP_TEXT
2552)     ),
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

2553)     cls=CompatibilityOption,
2554) )
Marco Ricci Allow unsetting settings wh...

Marco Ricci authored 3 weeks ago

2555) @click.option(
2556)     '--unset',
2557)     'unset_settings',
2558)     multiple=True,
2559)     type=click.Choice([
2560)         'phrase',
2561)         'key',
2562)         'length',
2563)         'repeat',
2564)         'lower',
2565)         'upper',
2566)         'number',
2567)         'space',
2568)         'dash',
2569)         'symbol',
2570)     ]),
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2571)     help=_msg.TranslatedString(
2572)         _msg.Label.DERIVEPASSPHRASE_VAULT_UNSET_HELP_TEXT
Marco Ricci Allow unsetting settings wh...

Marco Ricci authored 3 weeks ago

2573)     ),
2574)     cls=CompatibilityOption,
2575) )
Marco Ricci Support exporting the `vaul...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

2580)     help=_msg.TranslatedString(
2581)         _msg.Label.DERIVEPASSPHRASE_VAULT_EXPORT_AS_HELP_TEXT
2582)     ),
Marco Ricci Support exporting the `vaul...

Marco Ricci authored 2 weeks ago

2583)     cls=CompatibilityOption,
2584) )
Marco Ricci Reimplement `--help` and `-...

Marco Ricci authored 1 week ago

2585) @version_option
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

2586) @color_forcing_pseudo_option
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

2588) @click.argument(
2589)     'service',
2590)     metavar=_msg.TranslatedString(_msg.Label.VAULT_METAVAR_SERVICE),
2591)     required=False,
2592)     default=None,
Marco Ricci Add shell completion suppor...

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 5 months ago

2597)     ctx: click.Context,
2598)     /,
2599)     *,
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

2600)     service: str | None = None,
2601)     use_phrase: bool = False,
2602)     use_key: bool = False,
2603)     length: int | None = None,
2604)     repeat: int | None = None,
2605)     lower: int | None = None,
2606)     upper: int | None = None,
2607)     number: int | None = None,
2608)     space: int | None = None,
2609)     dash: int | None = None,
2610)     symbol: int | None = None,
2611)     edit_notes: bool = False,
2612)     store_config_only: bool = False,
2613)     delete_service_settings: bool = False,
2614)     delete_globals: bool = False,
2615)     clear_all_settings: bool = False,
2616)     export_settings: TextIO | pathlib.Path | os.PathLike[str] | None = None,
2617)     import_settings: TextIO | pathlib.Path | os.PathLike[str] | None = None,
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

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

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 6 months ago

2623) 
2624)     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

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 6 months ago

2631) 
2632)     Parameters:
2633)         ctx (click.Context):
2634)             The `click` context.
2635) 
2636)     Other Parameters:
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

2689)         export_settings:
2690)             Command-line argument `-e`/`--export`.  If a file object,
2691)             then it must be open for writing and accept `str` inputs.
2692)             Otherwise, a filename to open for writing.  Using `-` for
2693)             standard output is supported.
2694)         import_settings:
2695)             Command-line argument `-i`/`--import`.  If a file object, it
2696)             must be open for reading and yield `str` values.  Otherwise,
2697)             a filename to open for reading.  Using `-` for standard
2698)             input is supported.
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

2699)         overwrite_config:
2700)             Command-line arguments `--overwrite-existing` (True) and
2701)             `--merge-existing` (False).  Controls whether config saving
2702)             and config importing overwrite existing configurations, or
2703)             merge them section-wise instead.
Marco Ricci Allow unsetting settings wh...

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 3 months ago

2725)             elif isinstance(param, ConfigurationOption):
2726)                 group = ConfigurationOption
2727)             elif isinstance(param, StorageManagementOption):
2728)                 group = StorageManagementOption
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 4 weeks ago

2731)             elif isinstance(param, CompatibilityOption):
2732)                 group = CompatibilityOption
Marco Ricci Fix coverage

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 week ago

2734)                 group = StandardOption
Marco Ricci Fix coverage

Marco Ricci authored 1 week ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 6 months ago

2741)             options_in_group.setdefault(group, []).append(param)
2742)         params_by_str[param.human_readable_name] = param
2743)         for name in param.opts + param.secondary_opts:
2744)             params_by_str[name] = param
2745) 
Marco Ricci Rewrite incompatible option...

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 2 weeks ago

2750)     def option_name(param: click.Parameter | str) -> str:
2751)         # Annoyingly, `param.human_readable_name` contains the *function*
2752)         # parameter name, not the list of option names.  *Those* are
2753)         # stashed in the `.opts` and `.secondary_opts` attributes, which
2754)         # are visible in the `.to_info_dict()` output, but not otherwise
2755)         # documented.
2756)         param = params_by_str[param] if isinstance(param, str) else param
2757)         names = [param.human_readable_name, *param.opts, *param.secondary_opts]
2758)         option_names = [n for n in names if n.startswith('--')]
2759)         return min(option_names, key=len)
2760) 
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 weeks ago

2765)         param1 = params_by_str[param1] if isinstance(param1, str) else param1
2766)         param2 = params_by_str[param2] if isinstance(param2, str) else param2
2767)         if param1 == param2:
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

2768)             return
Marco Ricci Rewrite incompatible option...

Marco Ricci authored 3 weeks ago

2769)         if not is_param_set(param1):
2770)             return
2771)         if is_param_set(param2):
Marco Ricci Make the mutually exclusive...

Marco Ricci authored 2 weeks ago

2772)             param1_str = option_name(param1)
2773)             param2_str = option_name(param2)
Marco Ricci Rewrite incompatible option...

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

2776)                 str(
2777)                     _msg.TranslatedString(
2778)                         _msg.ErrMsgTemplate.PARAMS_MUTUALLY_EXCLUSIVE,
2779)                         param1=param1_str,
2780)                         param2=param2_str,
2781)                     )
2782)                 ),
Marco Ricci Make the mutually exclusive...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 3 weeks ago

2784)             )
2785)         return
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 1 month ago

2788)         stacklevel = kwargs.pop('stacklevel', 1)
2789)         stacklevel += 1
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

2790)         extra = kwargs.pop('extra', {})
2791)         extra.setdefault('color', ctx.color)
2792)         logger.error(msg, stacklevel=stacklevel, extra=extra, **kwargs)
Marco Ricci Use better error message ha...

Marco Ricci authored 4 months ago

2793)         ctx.exit(1)
2794) 
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

2796)         try:
2797)             return _load_config()
2798)         except FileNotFoundError:
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

2799)             try:
2800)                 backup_config, exc = _migrate_and_load_old_config()
2801)             except FileNotFoundError:
2802)                 return {'services': {}}
Marco Ricci Make obtaining the compatib...

Marco Ricci authored 3 weeks ago

2803)             old_name = os.path.basename(
2804)                 _config_filename(subsystem='old settings.json')
2805)             )
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

2808)                 _msg.TranslatedString(
2809)                     _msg.WarnMsgTemplate.V01_STYLE_CONFIG,
2810)                     old=old_name,
2811)                     new=new_name,
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

2812)                 ),
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

2813)                 extra={'color': ctx.color},
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

2814)             )
2815)             if isinstance(exc, OSError):
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

2817)                     _msg.TranslatedString(
2818)                         _msg.WarnMsgTemplate.FAILED_TO_MIGRATE_CONFIG,
2819)                         path=new_name,
2820)                         error=exc.strerror,
2821)                         filename=exc.filename,
2822)                     ).maybe_without_filename(),
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

2823)                     extra={'color': ctx.color},
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

2824)                 )
2825)             else:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2826)                 deprecation.info(
2827)                     _msg.TranslatedString(
2828)                         _msg.InfoMsgTemplate.SUCCESSFULLY_MIGRATED,
2829)                         path=new_name,
2830)                     ),
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

2831)                     extra={'color': ctx.color},
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2832)                 )
Marco Ricci Rename the configuration fi...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

2835)             err(
2836)                 _msg.TranslatedString(
2837)                     _msg.ErrMsgTemplate.CANNOT_LOAD_VAULT_SETTINGS,
2838)                     error=exc.strerror,
2839)                     filename=exc.filename,
2840)                 ).maybe_without_filename(),
2841)             )
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

2843)             err(
2844)                 _msg.TranslatedString(
2845)                     _msg.ErrMsgTemplate.CANNOT_LOAD_VAULT_SETTINGS,
2846)                     error=str(exc),
2847)                     filename=None,
2848)                 ).maybe_without_filename(),
2849)                 exc_info=exc,
2850)             )
Marco Ricci Use better error message ha...

Marco Ricci authored 4 months ago

2851) 
2852)     def put_config(config: _types.VaultConfig, /) -> None:
2853)         try:
2854)             _save_config(config)
Marco Ricci Document and handle other e...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 1 week ago

2856)             err(
2857)                 _msg.TranslatedString(
2858)                     _msg.ErrMsgTemplate.CANNOT_STORE_VAULT_SETTINGS,
2859)                     error=exc.strerror,
2860)                     filename=exc.filename,
2861)                 ).maybe_without_filename(),
2862)             )
Marco Ricci Use better error message ha...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 1 week ago

2864)             err(
2865)                 _msg.TranslatedString(
2866)                     _msg.ErrMsgTemplate.CANNOT_STORE_VAULT_SETTINGS,
2867)                     error=str(exc),
2868)                     filename=None,
2869)                 ).maybe_without_filename(),
2870)                 exc_info=exc,
2871)             )
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 weeks ago

2873)     def get_user_config() -> dict[str, Any]:
2874)         try:
2875)             return _load_user_config()
2876)         except FileNotFoundError:
2877)             return {}
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

2879)             err(
2880)                 _msg.TranslatedString(
2881)                     _msg.ErrMsgTemplate.CANNOT_LOAD_USER_CONFIG,
2882)                     error=exc.strerror,
2883)                     filename=exc.filename,
2884)                 ).maybe_without_filename(),
2885)             )
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

2887)             err(
2888)                 _msg.TranslatedString(
2889)                     _msg.ErrMsgTemplate.CANNOT_LOAD_USER_CONFIG,
2890)                     error=str(exc),
2891)                     filename=None,
2892)                 ).maybe_without_filename(),
2893)                 exc_info=exc,
2894)             )
Marco Ricci Introduce a central user co...

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

2897) 
2898)     check_incompatible_options('--phrase', '--key')
Marco Ricci Add prototype command-line...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 weeks ago

2907)             for other_opt in options_in_group[ConfigurationOption]:
2908)                 check_incompatible_options(opt, other_opt)
2909)             for other_opt in options_in_group[StorageManagementOption]:
2910)                 check_incompatible_options(opt, other_opt)
Marco Ricci Add an actual derivepassphr...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 2 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 1 week ago

2916)             err_msg = _msg.TranslatedString(
2917)                 _msg.ErrMsgTemplate.PARAMS_NEEDS_SERVICE_OR_CONFIG,
2918)                 param=param.opts[0],
2919)                 service_metavar=service_metavar,
2920)             )
2921)             raise click.UsageError(str(err_msg))  # noqa: DOC501
Marco Ricci Correctly model vault globa...

Marco Ricci authored 2 months ago

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

Marco Ricci authored 1 week ago

2925)             err_msg = _msg.TranslatedString(
2926)                 _msg.ErrMsgTemplate.PARAMS_NEEDS_SERVICE,
2927)                 param=param.opts[0],
2928)                 service_metavar=service_metavar,
2929)             )
2930)             raise click.UsageError(str(err_msg))
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

2931)     no_sv_options = [
2932)         params_by_str['--delete-globals'],
2933)         params_by_str['--clear'],
2934)         *options_in_group[StorageManagementOption],
2935)     ]
Marco Ricci Fortify the argument parsin...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 1 week ago

2938)             err_msg = _msg.TranslatedString(
2939)                 _msg.ErrMsgTemplate.PARAMS_NO_SERVICE,
2940)                 param=param.opts[0],
2941)                 service_metavar=service_metavar,
2942)             )
2943)             raise click.UsageError(str(err_msg))
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 weeks ago

2945)     user_config = get_user_config()
2946) 
Marco Ricci Warn the user upon supplyin...

Marco Ricci authored 2 months ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

2949)             _msg.TranslatedString(
2950)                 _msg.WarnMsgTemplate.EMPTY_SERVICE_NOT_SUPPORTED,
2951)                 service_metavar=service_metavar,
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

2952)             ),
2953)             extra={'color': ctx.color},
Marco Ricci Warn the user upon supplyin...

Marco Ricci authored 2 months ago

2954)         )
2955) 
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

2956)     if edit_notes:
2957)         assert service is not None
2958)         configuration = get_config()
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

2965)             while notes_lines:
2966)                 line = notes_lines.popleft()
2967)                 if line.startswith(DEFAULT_NOTES_MARKER):
2968)                     notes_value = ''.join(notes_lines)
2969)                     break
2970)             else:
2971)                 if not notes_value.strip():
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

2972)                     err(
2973)                         _msg.TranslatedString(
2974)                             _msg.ErrMsgTemplate.USER_ABORTED_EDIT
2975)                         )
2976)                     )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 5 months ago

2978)                 notes_value.strip('\n')
2979)             )
Marco Ricci Use better error message ha...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

2981)     elif delete_service_settings:
2982)         assert service is not None
2983)         configuration = get_config()
2984)         if service in configuration['services']:
2985)             del configuration['services'][service]
Marco Ricci Use better error message ha...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

2987)     elif delete_globals:
2988)         configuration = get_config()
2989)         if 'global' in configuration:
2990)             del configuration['global']
Marco Ricci Use better error message ha...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

2994)     elif import_settings:
2995)         try:
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 weeks ago

2998)             infile = cast(
2999)                 TextIO,
3000)                 (
3001)                     import_settings
3002)                     if hasattr(import_settings, 'close')
3003)                     else click.open_file(os.fspath(import_settings), 'rt')
3004)                 ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

3014)             err(
3015)                 _msg.TranslatedString(
3016)                     _msg.ErrMsgTemplate.CANNOT_DECODEIMPORT_VAULT_SETTINGS,
3017)                     error=exc,
3018)                 )
3019)             )
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

3021)             err(
3022)                 _msg.TranslatedString(
3023)                     _msg.ErrMsgTemplate.CANNOT_IMPORT_VAULT_SETTINGS,
3024)                     error=exc.strerror,
3025)                     filename=exc.filename,
3026)                 ).maybe_without_filename()
3027)             )
Marco Ricci Signal and list falsy value...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 1 week ago

3030)             err(
3031)                 _msg.TranslatedString(
3032)                     _msg.ErrMsgTemplate.CANNOT_IMPORT_VAULT_SETTINGS,
3033)                     error=_msg.TranslatedString(
3034)                         _msg.ErrMsgTemplate.INVALID_VAULT_CONFIG,
3035)                         config=maybe_config,
3036)                     ),
3037)                     filename=None,
3038)                 ).maybe_without_filename()
3039)             )
Marco Ricci Signal and list falsy value...

Marco Ricci authored 3 months ago

3040)         assert cleaned is not None
3041)         for step in cleaned:
3042)             # These are never fatal errors, because the semantics of
3043)             # vault upon encountering these settings are ill-specified,
3044)             # but not ill-defined.
3045)             if step.action == 'replace':
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

3047)                     _msg.TranslatedString(
3048)                         _msg.WarnMsgTemplate.STEP_REPLACE_INVALID_VALUE,
3049)                         old=json.dumps(step.old_value),
3050)                         path=_types.json_path(step.path),
3051)                         new=json.dumps(step.new_value),
3052)                     ),
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

3053)                     extra={'color': ctx.color},
Marco Ricci Signal and list falsy value...

Marco Ricci authored 3 months ago

3054)                 )
3055)             else:
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

3057)                     _msg.TranslatedString(
3058)                         _msg.WarnMsgTemplate.STEP_REMOVE_INEFFECTIVE_VALUE,
3059)                         path=_types.json_path(step.path),
3060)                         old=json.dumps(step.old_value),
3061)                     ),
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

3062)                     extra={'color': ctx.color},
Marco Ricci Signal and list falsy value...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 2 months ago

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

Marco Ricci authored 1 month ago

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

Marco Ricci authored 1 week ago

3066)                 _msg.TranslatedString(
3067)                     _msg.WarnMsgTemplate.EMPTY_SERVICE_SETTINGS_INACCESSIBLE,
3068)                     service_metavar=service_metavar,
3069)                     PROG_NAME=PROG_NAME,
Marco Ricci Use the logging system to e...

Marco Ricci authored 1 month ago

3070)                 ),
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

3071)                 extra={'color': ctx.color},
Marco Ricci Warn the user upon supplyin...

Marco Ricci authored 2 months ago

3072)             )
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 weeks ago

3075)                 ('global',),
3076)                 cast(dict[str, Any], maybe_config.get('global', {})),
3077)                 main_config=user_config,
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

3078)                 ctx=ctx,
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

3079)             )
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

3080)             for key, value in maybe_config['services'].items():
3081)                 _check_for_misleading_passphrase(
3082)                     ('services', key),
3083)                     cast(dict[str, Any], value),
3084)                     main_config=user_config,
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

3085)                     ctx=ctx,
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

3086)                 )
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

3088)             err(
3089)                 _msg.TranslatedString(
3090)                     _msg.ErrMsgTemplate.INVALID_USER_CONFIG,
3091)                     error=exc,
3092)                     filename=None,
3093)                 ).maybe_without_filename(),
3094)             )
Marco Ricci Fix empty key handling in `...

Marco Ricci authored 3 weeks ago

3095)         global_obj = maybe_config.get('global', {})
3096)         has_key = _types.js_truthiness(global_obj.get('key'))
3097)         has_phrase = _types.js_truthiness(global_obj.get('phrase'))
3098)         if has_key and has_phrase:
3099)             logger.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3100)                 _msg.TranslatedString(
3101)                     _msg.WarnMsgTemplate.GLOBAL_PASSPHRASE_INEFFECTIVE,
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

3102)                 ),
3103)                 extra={'color': ctx.color},
Marco Ricci Fix empty key handling in `...

Marco Ricci authored 3 weeks ago

3104)             )
3105)         for service_name, service_obj in maybe_config['services'].items():
3106)             has_key = _types.js_truthiness(
3107)                 service_obj.get('key')
3108)             ) or _types.js_truthiness(global_obj.get('key'))
3109)             has_phrase = _types.js_truthiness(
3110)                 service_obj.get('phrase')
3111)             ) or _types.js_truthiness(global_obj.get('phrase'))
3112)             if has_key and has_phrase:
3113)                 logger.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3114)                     _msg.TranslatedString(
3115)                         _msg.WarnMsgTemplate.SERVICE_PASSPHRASE_INEFFECTIVE,
3116)                         service=json.dumps(service_name),
Marco Ricci Fix empty key handling in `...

Marco Ricci authored 3 weeks ago

3117)                     ),
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

3118)                     extra={'color': ctx.color},
Marco Ricci Fix empty key handling in `...

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 4 weeks ago

3120)         if overwrite_config:
3121)             put_config(maybe_config)
3122)         else:
3123)             configuration = get_config()
3124)             merged_config: collections.ChainMap[str, Any] = (
3125)                 collections.ChainMap(
3126)                     {
3127)                         'services': collections.ChainMap(
3128)                             maybe_config['services'],
3129)                             configuration['services'],
3130)                         ),
3131)                     },
3132)                     {'global': maybe_config['global']}
3133)                     if 'global' in maybe_config
3134)                     else {},
3135)                     {'global': configuration['global']}
3136)                     if 'global' in configuration
3137)                     else {},
3138)                 )
3139)             )
3140)             new_config: Any = {
3141)                 k: dict(v) if isinstance(v, collections.ChainMap) else v
3142)                 for k, v in sorted(merged_config.items())
3143)             }
3144)             assert _types.is_vault_config(new_config)
3145)             put_config(new_config)
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3146)     elif export_settings:
3147)         configuration = get_config()
3148)         try:
Marco Ricci Apply new ruff ruleset to c...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 weeks ago

3151)             outfile = cast(
3152)                 TextIO,
3153)                 (
3154)                     export_settings
3155)                     if hasattr(export_settings, 'close')
3156)                     else click.open_file(os.fspath(export_settings), 'wt')
3157)                 ),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 2 weeks ago

3165)                 if export_as == 'sh':
3166)                     this_ctx = ctx
3167)                     prog_name_pieces = collections.deque([
3168)                         this_ctx.info_name or 'vault',
3169)                     ])
3170)                     while (
3171)                         this_ctx.parent is not None
3172)                         and this_ctx.parent.info_name is not None
3173)                     ):
3174)                         prog_name_pieces.appendleft(this_ctx.parent.info_name)
3175)                         this_ctx = this_ctx.parent
3176)                     _print_config_as_sh_script(
3177)                         configuration,
3178)                         outfile=outfile,
3179)                         prog_name_list=prog_name_pieces,
3180)                     )
3181)                 else:
3182)                     json.dump(configuration, outfile)
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

3184)             err(
3185)                 _msg.TranslatedString(
3186)                     _msg.ErrMsgTemplate.CANNOT_EXPORT_VAULT_SETTINGS,
3187)                     error=exc.strerror,
3188)                     filename=exc.filename,
3189)                 ).maybe_without_filename(),
3190)             )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 5 months ago

3198)         service_keys = {
3199)             'key',
3200)             'phrase',
3201)             'length',
3202)             'repeat',
3203)             'lower',
3204)             'upper',
3205)             'number',
3206)             'space',
3207)             'dash',
3208)             'symbol',
3209)         }
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 5 months ago

3211)             {
3212)                 k: v
3213)                 for k, v in locals().items()
3214)                 if k in service_keys and v is not None
3215)             },
3216)             cast(
3217)                 dict[str, Any],
3218)                 configuration['services'].get(service or '', {}),
3219)             ),
3220)             cast(dict[str, Any], configuration.get('global', {})),
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3221)         )
3222)         if use_key:
3223)             try:
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

3224)                 key = base64.standard_b64encode(
3225)                     _select_ssh_key(ctx=ctx)
3226)                 ).decode('ASCII')
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 1 week ago

3228)                 err(
3229)                     _msg.TranslatedString(
3230)                         _msg.ErrMsgTemplate.USER_ABORTED_SSH_KEY_SELECTION
3231)                     ),
3232)                 )
Marco Ricci Document and handle other e...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 1 week ago

3235)                     _msg.TranslatedString(
3236)                         _msg.ErrMsgTemplate.NO_SSH_AGENT_FOUND
3237)                     ),
3238)                 )
3239)             except LookupError:
3240)                 err(
3241)                     _msg.TranslatedString(
3242)                         _msg.ErrMsgTemplate.NO_SUITABLE_SSH_KEYS,
3243)                         PROG_NAME=PROG_NAME,
3244)                     )
Marco Ricci Fail gracefully if UNIX dom...

Marco Ricci authored 3 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

3249)                 err(
3250)                     _msg.TranslatedString(
3251)                         _msg.ErrMsgTemplate.CANNOT_CONNECT_TO_AGENT,
3252)                         error=exc.strerror,
3253)                         filename=exc.filename,
3254)                     ).maybe_without_filename(),
3255)                 )
3256)             except ssh_agent.SSHAgentFailedError as exc:
3257)                 err(
3258)                     _msg.TranslatedString(
3259)                         _msg.ErrMsgTemplate.AGENT_REFUSED_LIST_KEYS
3260)                     ),
3261)                     exc_info=exc,
3262)                 )
3263)             except RuntimeError as exc:
3264)                 err(
3265)                     _msg.TranslatedString(
3266)                         _msg.ErrMsgTemplate.CANNOT_UNDERSTAND_AGENT
3267)                     ),
3268)                     exc_info=exc,
3269)                 )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3270)         elif use_phrase:
3271)             maybe_phrase = _prompt_for_passphrase()
3272)             if not maybe_phrase:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3273)                 err(
3274)                     _msg.TranslatedString(
3275)                         _msg.ErrMsgTemplate.USER_ABORTED_PASSPHRASE
3276)                     )
3277)                 )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3278)             else:
3279)                 phrase = maybe_phrase
3280)         if store_config_only:
3281)             view: collections.ChainMap[str, Any]
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

3282)             view = (
3283)                 collections.ChainMap(*settings.maps[:2])
3284)                 if service
Marco Ricci Fix missing consideration o...

Marco Ricci authored 2 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 6 months ago

3287)             if use_key:
3288)                 view['key'] = key
3289)             elif use_phrase:
Marco Ricci Fix missing consideration o...

Marco Ricci authored 2 months ago

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

Marco Ricci authored 3 weeks ago

3292)                 try:
3293)                     _check_for_misleading_passphrase(
3294)                         ('services', service) if service else ('global',),
3295)                         {'phrase': phrase},
3296)                         main_config=user_config,
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

3297)                         ctx=ctx,
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

3298)                     )
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

3300)                     err(
3301)                         _msg.TranslatedString(
3302)                             _msg.ErrMsgTemplate.INVALID_USER_CONFIG,
3303)                             error=exc,
3304)                             filename=None,
3305)                         ).maybe_without_filename(),
3306)                     )
Marco Ricci Fix missing consideration o...

Marco Ricci authored 2 months ago

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

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 1 week ago

3310)                             _msg.TranslatedString(
3311)                                 _msg.WarnMsgTemplate.SERVICE_PASSPHRASE_INEFFECTIVE,
3312)                                 service=json.dumps(service),
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

3313)                             ),
3314)                             extra={'color': ctx.color},
Marco Ricci Fix empty key handling in `...

Marco Ricci authored 3 weeks ago

3315)                         )
3316)                     else:
3317)                         logger.warning(
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3318)                             _msg.TranslatedString(
3319)                                 _msg.WarnMsgTemplate.GLOBAL_PASSPHRASE_INEFFECTIVE
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

3320)                             ),
3321)                             extra={'color': ctx.color},
Marco Ricci Fix empty key handling in `...

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

3325)                 err_msg = _msg.TranslatedString(
3326)                     _msg.ErrMsgTemplate.CANNOT_UPDATE_SETTINGS_NO_SETTINGS,
3327)                     settings_type=settings_type,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 1 week ago

3332)                     err_msg = _msg.TranslatedString(
3333)                         _msg.ErrMsgTemplate.SET_AND_UNSET_SAME_SETTING,
3334)                         setting=setting,
Marco Ricci Allow unsetting settings wh...

Marco Ricci authored 3 weeks ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 4 weeks ago

3337)             subtree: dict[str, Any] = (
3338)                 configuration['services'].setdefault(service, {})  # type: ignore[assignment]
3339)                 if service
3340)                 else configuration.setdefault('global', {})
3341)             )
3342)             if overwrite_config:
3343)                 subtree.clear()
Marco Ricci Allow unsetting settings wh...

Marco Ricci authored 3 weeks ago

3344)             else:
3345)                 for setting in unset_settings:
3346)                     subtree.pop(setting, None)
Marco Ricci Allow the user to overwrite...

Marco Ricci authored 4 weeks ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

3352)         else:
3353)             if not service:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3354)                 err_msg = _msg.TranslatedString(
3355)                     _msg.ErrMsgTemplate.SERVICE_REQUIRED,
3356)                     service_metavar=_msg.TranslatedString(
3357)                         _msg.Label.VAULT_METAVAR_SERVICE
3358)                     ),
3359)                 )
3360)                 raise click.UsageError(str(err_msg))
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

3361)             kwargs: dict[str, Any] = {
3362)                 k: v
3363)                 for k, v in settings.items()
3364)                 if k in service_keys and v is not None
3365)             }
3366) 
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 weeks ago

3368)                 try:
3369)                     _check_for_misleading_passphrase(
3370)                         _ORIGIN.INTERACTIVE,
3371)                         {'phrase': phrase},
3372)                         main_config=user_config,
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

3373)                         ctx=ctx,
Marco Ricci Turn Unicode normalization...

Marco Ricci authored 3 weeks ago

3374)                     )
Marco Ricci Add small fixes to changelo...

Marco Ricci authored 2 weeks ago

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

Marco Ricci authored 1 week ago

3376)                     err(
3377)                         _msg.TranslatedString(
3378)                             _msg.ErrMsgTemplate.INVALID_USER_CONFIG,
3379)                             error=exc,
3380)                             filename=None,
3381)                         ).maybe_without_filename(),
3382)                     )
Marco Ricci Allow all textual strings,...

Marco Ricci authored 4 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 6 months ago

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

Marco Ricci authored 2 weeks ago

3391)                 kwargs['phrase'] = (
3392)                     _key_to_phrase(key, error_callback=err)
3393)                     if use_key
3394)                     else phrase
3395)                 )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

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

Marco Ricci authored 3 weeks ago

3397)                 kwargs['phrase'] = _key_to_phrase(
3398)                     kwargs['key'], error_callback=err
3399)                 )
Marco Ricci Add finished command-line i...

Marco Ricci authored 6 months ago

3400)             elif kwargs.get('phrase'):
3401)                 pass
3402)             else:
Marco Ricci Update the CLI to use the t...

Marco Ricci authored 1 week ago

3403)                 err_msg = _msg.TranslatedString(
3404)                     _msg.ErrMsgTemplate.NO_KEY_OR_PHRASE
Marco Ricci Reformat everything with ruff

Marco Ricci authored 5 months ago

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

Marco Ricci authored 1 week ago

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

Marco Ricci authored 5 months ago

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

Marco Ricci authored 5 months ago

3408)             result = vault.Vault(**kwargs).generate(service)
Marco Ricci Support suppressing or forc...

Marco Ricci authored 1 week ago

3409)             click.echo(result.decode('ASCII'), color=ctx.color)