1#!/usr/bin/env python3
2"""
3
4"""
5# Imports:
6from __future__ import annotations
7
8# ##-- stdlib imports
9import datetime
10import enum
11import functools as ftz
12import itertools as itz
13import logging as logmod
14import pathlib as pl
15import re
16import time
17import types
18import weakref
19from uuid import UUID, uuid1
20
21# ##-- end stdlib imports
22
23from . import _interface as API # noqa: N812
24from .subclasser import Subclasser
25
26# ##-- types
27# isort: off
28import abc
29import collections.abc
30from typing import TYPE_CHECKING, Generic, cast, assert_type, assert_never, NewType, _caller # type: ignore[attr-defined]
31from types import GenericAlias
32from typing import TypeAliasType
33# Protocols:
34from typing import Protocol, runtime_checkable
35# Typing Decorators:
36from typing import no_type_check, final, override, overload
37from types import resolve_bases
38from pydantic import BaseModel, create_model
39
40if TYPE_CHECKING:
41 from jgdv import Maybe, Rx
42 from typing import Final
43 from typing import ClassVar, Any, LiteralString
44 from typing import Never, Self, Literal
45 from typing import TypeGuard
46 from collections.abc import Iterable, Iterator, Callable, Generator
47 from collections.abc import Sequence, Mapping, MutableMapping, Hashable
48
49# isort: on
50# ##-- end types
51
52##-- logging
53logging = logmod.getLogger(__name__)
54##-- end logging
55
56##--| Vars
57
58##--| Body
59
[docs]
60class SubAnnotate_m:
61 """
62 A Mixin to create simple subclasses through annotation.
63 Annotation var name can be customized through the subclass kwarg 'annotate_to'.
64 eg:
65
66 class MyExample(SubAnnotate_m, annotate_to='blah'):
67 pass
68
69 a_sub = MyExample[int]
70 a_sub.__class__.blah == int
71
72 """
73 __slots__ = ()
74
75 __builder : ClassVar[Subclasser] = Subclasser()
76 _annotate_to : ClassVar[str] = API.AnnotationTarget
77
78 @override
79 def __init_subclass__(cls, *args:Any, **kwargs:Any) -> None:
80 """ On init of a subclass, ensure it's annotation target is set
81
82 """
83 super().__init_subclass__(*args)
84 match kwargs.pop(API.AnnotateKWD, None):
85 case str() as target:
86 logging.debug("Annotate Subclassing: %s : %s", cls, kwargs)
87 cls._annotate_to = target
88 setattr(cls, cls._annotate_to, None)
89 case None if not hasattr(cls, cls._annotate_to):
90 setattr(cls, cls._annotate_to, None)
91 case _:
92 pass
93
94 @classmethod
95 @ftz.cache
96 def __class_getitem__[T:SubAnnotate_m](cls:type[T], *params:Any) -> type[T]: # noqa: ANN401
97 """ Auto-subclass as {cls.__name__}[param]
98
99 Caches results to avoid duplicates
100 """
101 logging.debug("Annotating: %s : %s : (%s)", cls.__name__, params, cls._annotate_to) # type: ignore[attr-defined]
102 match params:
103 case []:
104 return cls
105 case _:
106 return cls.__builder.annotate(cls, *params)
107
[docs]
108 @classmethod
109 def cls_annotation(cls) -> Maybe[str]:
110 return getattr(cls, cls._annotate_to, None)