Coverage for .tox/coverage/lib/python3.11/site-packages/wuttjamaican/cli/base.py: 100%

20 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-12-29 12:53 -0600

1# -*- coding: utf-8; -*- 

2################################################################################ 

3# 

4# WuttJamaican -- Base package for Wutta Framework 

5# Copyright © 2023-2025 Lance Edgar 

6# 

7# This file is part of Wutta Framework. 

8# 

9# Wutta Framework is free software: you can redistribute it and/or modify it 

10# under the terms of the GNU General Public License as published by the Free 

11# Software Foundation, either version 3 of the License, or (at your option) any 

12# later version. 

13# 

14# Wutta Framework is distributed in the hope that it will be useful, but 

15# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 

16# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 

17# more details. 

18# 

19# You should have received a copy of the GNU General Public License along with 

20# Wutta Framework. If not, see <http://www.gnu.org/licenses/>. 

21# 

22################################################################################ 

23""" 

24WuttJamaican - core command logic 

25 

26See also :doc:`/narr/cli/index`. 

27 

28.. data:: wutta_typer 

29 

30 This is the top-level ``wutta`` :term:`command`, using the Typer 

31 framework. 

32 

33 See also :func:`make_typer()`. 

34""" 

35 

36import logging 

37from pathlib import Path 

38from typing import List, Optional 

39 

40import typer 

41from typing_extensions import Annotated 

42 

43from wuttjamaican.conf import make_config 

44from wuttjamaican.util import load_entry_points 

45 

46 

47def make_cli_config(ctx: typer.Context): 

48 """ 

49 Make a :term:`config object` according to the command-line context 

50 (params). 

51 

52 This function is normally called by :func:`typer_callback()`. 

53 

54 This function calls :func:`~wuttjamaican.conf.make_config()` using 

55 config files specified via command line (if any). 

56 

57 :param ctx: ``typer.Context`` instance 

58 

59 :returns: :class:`~wuttjamaican.conf.WuttaConfig` instance 

60 """ 

61 logging.basicConfig() 

62 return make_config(files=ctx.params.get("config_paths") or None) 

63 

64 

65def typer_callback( # pylint: disable=unused-argument 

66 ctx: typer.Context, 

67 config_paths: Annotated[ 

68 Optional[List[Path]], 

69 typer.Option( 

70 "--config", 

71 "-c", 

72 exists=True, 

73 help="Config path (may be specified more than once)", 

74 ), 

75 ] = None, 

76 runas_username: Annotated[ 

77 str, 

78 typer.Option( 

79 "--runas", 

80 help="Username responsible for running the command (where applicable).", 

81 ), 

82 ] = None, 

83 comment: Annotated[ 

84 str, 

85 typer.Option( 

86 "--comment", 

87 "-m", 

88 help="Comment to apply to the transaction (where applicable).", 

89 ), 

90 ] = None, 

91): 

92 """ 

93 Generic callback for use with top-level commands. This adds some 

94 top-level args: 

95 

96 * ``--config`` (and/or ``-c``) 

97 * ``--runas`` 

98 * ``--comment`` (or ``-m``) 

99 

100 This callback is responsible for creating the :term:`config 

101 object` for the command. (It calls :func:`make_cli_config()` for 

102 that.) It then attaches it to the context as 

103 ``ctx.wutta_config``. 

104 """ 

105 ctx.wutta_config = make_cli_config(ctx) 

106 

107 

108def typer_eager_imports(group: [typer.Typer, str]): 

109 """ 

110 Eagerly import all modules which are registered as having 

111 :term:`subcommands <subcommand>` belonging to the given group 

112 (i.e. top-level :term:`command`). 

113 

114 This is used to locate subcommands which may be defined by 

115 multiple different packages. It is mostly needed for the main 

116 ``wutta`` command, since e.g. various extension packages may 

117 define additional subcommands for it. 

118 

119 Most custom apps will define their own top-level command and some 

120 subcommands, but will have no need to "discover" additional 

121 subcommands defined elsewhere. Hence you normally would not need 

122 to call this function. 

123 

124 However if you wish to define a ``wutta`` subcommand(s), you 

125 *would* need to register the entry point for your module(s) 

126 containing the subcommand(s) like so (in ``pyproject.toml``): 

127 

128 .. code-block:: ini 

129 

130 [project.entry-points."wutta.typer_imports"] 

131 poser = "poser.commands" 

132 

133 Note that the ``wutta.typer_imports`` above indicates you are 

134 registering a module which defines ``wutta`` subcommands. The 

135 ``poser`` name is arbitrary but should match your package name. 

136 

137 :param group: Typer group command, or the name of one. 

138 """ 

139 if isinstance(group, typer.Typer): 

140 group = group.info.name 

141 load_entry_points(f"{group}.typer_imports") 

142 

143 

144def make_typer(**kwargs): 

145 """ 

146 Create a Typer command instance, per Wutta conventions. 

147 

148 This function is used to create the top-level ``wutta`` command, 

149 :data:`wutta_typer`. You can use it to create additional 

150 top-level commands for your app if needed. (And don't forget to 

151 register; see :doc:`/narr/cli/custom`.) 

152 

153 :param callback: Override for the ``Typer.callback`` param. If 

154 not specified, :func:`typer_callback` is used. 

155 

156 :returns: ``typer.Typer`` instance 

157 """ 

158 kwargs.setdefault("callback", typer_callback) 

159 return typer.Typer(**kwargs) 

160 

161 

162wutta_typer = make_typer(name="wutta", help="Wutta Software Framework")