1#!/usr/bin/env python3
2"""
3
4"""
5
6# Imports:
7from __future__ import annotations
8
9# ##-- stdlib imports
10import datetime
11import enum
12import functools as ftz
13import itertools as itz
14import logging as logmod
15import pathlib as pl
16import re
17import time
18import types
19import typing
20import weakref
21from uuid import UUID, uuid1
22
23# ##-- end stdlib imports
24
25# ##-- 3rd party imports
26from jgdv import Mixin, Proto
27from jgdv.cli import ParamSpecMaker_m
28# ##-- end 3rd party imports
29
30# ##-- 1st party imports
31import doot
32from ._interface import Command_p
33
34# ##-- end 1st party imports
35
36# ##-- types
37# isort: off
38import abc
39import collections.abc
40from typing import TYPE_CHECKING, cast, assert_type, assert_never
41from typing import Generic, NewType
42# Protocols:
43from typing import Protocol, runtime_checkable
44# Typing Decorators:
45from typing import no_type_check, final, override, overload
46
47if TYPE_CHECKING:
48 from jgdv.cli import ParamSpec_p
49 from jgdv import Maybe, Lambda
50 from jgdv.structs.chainguard import ChainGuard
51 from typing import Final
52 from typing import ClassVar, Any, LiteralString
53 from typing import Never, Self, Literal
54 from typing import TypeGuard
55 from collections.abc import Iterable, Iterator, Callable, Generator
56 from collections.abc import Sequence, Mapping, MutableMapping, Hashable
57
58 from doot.errors import DootError
59 type ListVal = Maybe[str|Lambda|tuple[str,dict]]
60
61# isort: on
62# ##-- end types
63
64##-- logging
65logging = logmod.getLogger(__name__)
66##-- end logging
67
[docs]
68@Proto(Command_p, check=False)
69@Mixin(ParamSpecMaker_m)
70class BaseCommand:
71 """ Generic implementations of command methods """
72 build_param : Callable
73 _help : ClassVar[tuple[str, ...]]
74
75 def __init__(self, name:Maybe[str]=None):
76 self._name = name
77
[docs]
78 @property
79 def name(self) -> str:
80 """get command name as used from command line"""
81 return self._name or self.__class__.__name__.lower()
82
[docs]
83 @property
84 def help(self) -> list[str]:
85 help_lines : list[str] = [
86 "", f"Command: {self.name}", "",
87 *list(self._help or []),
88 ]
89
90 params = self.param_specs()
91 if bool(params):
92 key_func = params[0].key_func
93 help_lines += ["", "Params:"]
94 help_lines += filter(lambda x: bool(x), (x.help_str() for x in sorted(self.param_specs(), key=key_func))) # type: ignore[arg-type]
95
96 return help_lines
97
[docs]
98 @property
99 def helpline(self) -> str:
100 """ get just the first line of the help text """
101 match self._help:
102 case [x, *_]:
103 return f" {self.name: <10} : {x}"
104 case _:
105 return f" {self.name: <10} :"
106
[docs]
107 def param_specs(self) -> list[ParamSpec_p]:
108 """
109 Provide parameter specs for parsing into doot.args.cmds
110 """
111 return [
112 self.build_param(name="--help", default=False, implicit=True),
113 self.build_param(name="--debug", default=False, implicit=True),
114 ]
115
[docs]
116 def _print_text(self, text:Iterable[ListVal]) -> None:
117 """ Utility method to print text out at the user level """
118 match text:
119 case str():
120 text = [text]
121 case [*_]:
122 pass
123 case x:
124 raise doot.errors.CommandError("Unknown type tried to be printed", x)
125
126 for line in text:
127 match line:
128 case str():
129 doot.report.gen.user(line)
130 case (str() as s, dict() as d):
131 doot.report.gen.user(s, extra=d)
132 case None:
133 doot.report.gen.user("")
134
135
136
[docs]
137 def shutdown(self, tasks:ChainGuard, plugins:ChainGuard, errored:Maybe[DootError]=None) -> None:
138 pass