1#!/usr/bin/env python3
2"""
3
4"""
5# Imports:
6from __future__ import annotations
7
8# ##-- stdlib imports
9import datetime
10import functools as ftz
11import itertools as itz
12import logging as logmod
13import re
14import time
15import types
16import typing
17import weakref
18from uuid import UUID, uuid1
19
20# ##-- end stdlib imports
21
22# ##-- types
23# isort: off
24import abc
25import collections.abc
26from typing import TYPE_CHECKING, cast, assert_type, assert_never
27from typing import Generic, NewType, Any
28# Protocols:
29from typing import Protocol, runtime_checkable
30# Typing Decorators:
31from typing import no_type_check, final, override, overload
32
33if TYPE_CHECKING:
34 import pathlib as pl
35 import enum
36 from typing import Final
37 from typing import ClassVar, LiteralString
38 from typing import Never, Self, Literal
39 from typing import TypeGuard
40 from collections.abc import Iterable, Iterator, Callable, Generator
41 from collections.abc import Sequence, Mapping, MutableMapping, Hashable
42
43 from ..types import Maybe, CtorFn
44 type ChainGuard = Any
45 type Logger = logmod.Logger
46
47# isort: on
48# ##-- end types
49
50##-- logging
51logging = logmod.getLogger(__name__)
52##-- end logging
53
54# ##-- Generated Exports
55__all__ = (
56
57# -- Classes
58"ActionGrouper_p", "ArtifactStruct_p", "Buildable_p", "DILogger_p",
59"ExecutableTask", "Factory_p", "FailHandler_p", "InstantiableSpecification_p",
60"Loader_p", "Nameable_p", "Persistent_p", "SpecStruct_p", "StubStruct_p",
61"TomlStubber_p", "UpToDate_p", "Visitor_p",
62
63)
64# ##-- end Generated Exports
65
[docs]
66@runtime_checkable
67class ArtifactStruct_p(Protocol):
68 """ Base class for artifacts, for type matching """
69
[docs]
70 def exists(self, *, data=None) -> bool: ... # noqa: ANN001
71
[docs]
72@runtime_checkable
73class UpToDate_p(Protocol):
74 """ For things (often artifacts) which might need to have actions done if they were created too long ago """
75
[docs]
76 def is_stale(self, *, other:Any=None) -> bool: ... # noqa: ANN401
77 """ Query whether the task's artifacts have become stale and need to be rebuilt"""
78
[docs]
79@runtime_checkable
80class StubStruct_p(Protocol):
81 """ Base class for stubs, for type matching """
82
[docs]
83 def to_toml(self) -> str: ...
84
[docs]
85@runtime_checkable
86class SpecStruct_p(Protocol):
87 """ Base class for specs, for type matching """
88
[docs]
89 @property
90 def params(self) -> dict|ChainGuard: ...
91
[docs]
92 @property
93 def args(self) -> list: ...
94
[docs]
95 @property
96 def kwargs(self) -> dict: ...
97
[docs]
98@runtime_checkable
99class TomlStubber_p(Protocol):
100 """
101 Something that can be turned into toml
102 """
103
[docs]
104 @classmethod
105 def class_help(cls) -> str: ...
106
[docs]
107 @classmethod
108 def stub_class(cls, stub:StubStruct_p) -> None: ...
109 """
110 Specialize a StubStruct_p to describe this class
111 """
112
[docs]
113 def stub_instance(self, stub:StubStruct_p) -> None: ...
114 """
115 Specialize a StubStruct_p with the settings of this specific instance
116 """
117
[docs]
118 @property
119 def short_doc(self) -> str: ...
120 """ Generate Job Class 1 line help string """
121
[docs]
122 @property
123 def doc(self) -> list[str]: ...
124
[docs]
125@runtime_checkable
126class ActionGrouper_p(Protocol):
127 """ For things have multiple named groups of actions """
128
[docs]
129 def get_group(self, name:str) -> Maybe[list]: ...
130
[docs]
131@runtime_checkable
132class Loader_p(Protocol):
133 """ The protocol for something that will load something from the system, a file, etc
134 TODO add a type parameter
135 """
136
[docs]
137 def setup(self, extra_config:ChainGuard) -> Self: ...
138
[docs]
139 def load(self) -> ChainGuard: ...
140
[docs]
141@runtime_checkable
142class Buildable_p(Protocol):
143 """ For things that need building, but don't have a separate factory
144 TODO add type parameter
145 """
146
[docs]
147 @classmethod
148 def build(cls, *args:Any) -> Self: ... # noqa: ANN401
149
[docs]
150@runtime_checkable
151class Factory_p[T](Protocol):
152 """
153 Factory protocol: {type}.build
154 """
155
[docs]
156 @classmethod
157 def build(cls:type[T], *args:Any, **kwargs:Any) -> T: ... # noqa: ANN401
158
[docs]
159@runtime_checkable
160class Nameable_p(Protocol):
161 """ The core protocol of something use as a name """
162
163 @override
164 def __hash__(self) -> int: ...
165
166 @override
167 def __eq__(self, other:object) -> bool: ...
168
169 def __lt__(self, other:Nameable_p) -> bool: ...
170
171 def __contains__(self, other:Nameable_p) -> bool: ...
172
[docs]
173@runtime_checkable
174class InstantiableSpecification_p(Protocol):
175 """ A Specification that can be instantiated further """
176
[docs]
177 def instantiate_onto(self, data:Maybe[Self]) -> Self: ...
178
[docs]
179 def make(self) -> Self: ...
180
[docs]
181@runtime_checkable
182class ExecutableTask(Protocol):
183 """ Runners pass off to Tasks/Jobs implementing this protocol
184 instead of using their default logic
185 """
186
[docs]
187 def setup(self) -> None: ...
188 """ """
189
[docs]
190 def expand(self) -> list: ...
191 """ For expanding a job into tasks """
192
[docs]
193 def execute(self) -> None: ...
194 """ For executing a task """
195
[docs]
196 def teardown(self) -> None: ...
197 """ For Cleaning up the task """
198
[docs]
199 def check_entry(self) -> bool: ...
200 """ For signifiying whether to expand/execute this object """
201
[docs]
202 def execute_action_group(self, group_name:str) -> enum.Enum|list: ...
203 """ Optional but recommended """
204
[docs]
205 def execute_action(self) -> None: ...
206 """ For executing a single action """
207
[docs]
208 def current_status(self) -> enum.Enum: ...
209
[docs]
210 def force_status(self, status:enum.Enum) -> None: ...
211
[docs]
212 def current_priority(self) -> int: ...
213
[docs]
214 def decrement_priority(self) -> None: ...
215
[docs]
216@runtime_checkable
217class Persistent_p(Protocol):
218 """ A Protocol for persisting data """
219
[docs]
220 def write(self, target:pl.Path) -> None: ...
221 """ Write this object to the target path """
222
[docs]
223 def read(self, target:pl.Path) -> None: ...
224 """ Read the target file, creating a new object """
225
[docs]
226@runtime_checkable
227class FailHandler_p(Protocol):
228
[docs]
229 def handle_failure(self, err:Exception, *args:Any, **kwargs:Any) -> Maybe[Any]: ... # noqa: ANN401
230
[docs]
231@runtime_checkable
232class Visitor_p(Protocol):
233
[docs]
234 def visit(self, **kwargs:Any) -> Any: ... # noqa: ANN401
235
[docs]
236@runtime_checkable
237class DILogger_p(Protocol):
238 """ Protocol for classes with a dependency injectable logger """
239
[docs]
240 def logger(self) -> Logger: ...