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
« 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
26See also :doc:`/narr/cli/index`.
28.. data:: wutta_typer
30 This is the top-level ``wutta`` :term:`command`, using the Typer
31 framework.
33 See also :func:`make_typer()`.
34"""
36import logging
37from pathlib import Path
38from typing import List, Optional
40import typer
41from typing_extensions import Annotated
43from wuttjamaican.conf import make_config
44from wuttjamaican.util import load_entry_points
47def make_cli_config(ctx: typer.Context):
48 """
49 Make a :term:`config object` according to the command-line context
50 (params).
52 This function is normally called by :func:`typer_callback()`.
54 This function calls :func:`~wuttjamaican.conf.make_config()` using
55 config files specified via command line (if any).
57 :param ctx: ``typer.Context`` instance
59 :returns: :class:`~wuttjamaican.conf.WuttaConfig` instance
60 """
61 logging.basicConfig()
62 return make_config(files=ctx.params.get("config_paths") or None)
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:
96 * ``--config`` (and/or ``-c``)
97 * ``--runas``
98 * ``--comment`` (or ``-m``)
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)
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`).
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.
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.
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``):
128 .. code-block:: ini
130 [project.entry-points."wutta.typer_imports"]
131 poser = "poser.commands"
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.
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")
144def make_typer(**kwargs):
145 """
146 Create a Typer command instance, per Wutta conventions.
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`.)
153 :param callback: Override for the ``Typer.callback`` param. If
154 not specified, :func:`typer_callback` is used.
156 :returns: ``typer.Typer`` instance
157 """
158 kwargs.setdefault("callback", typer_callback)
159 return typer.Typer(**kwargs)
162wutta_typer = make_typer(name="wutta", help="Wutta Software Framework")