Source code for jgdv.mixins.annotate.annotate

  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)