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 string
18import time
19import types
20import weakref
21from uuid import UUID, uuid1
22
23# ##-- end stdlib imports
24
25# ##-- 3rd party imports
26from pydantic import BaseModel, Field, field_validator, model_validator
27from jgdv.decorators import DecoratorAccessor_m
28from jgdv.structs.chainguard import ChainGuard
29from jgdv.structs.strang import CodeReference
30from jgdv.structs.dkey import DKey, DKeyMark_e, SingleDKey, MultiDKey, NonDKey, DKeyExpansionDecorator
31from jgdv.structs.dkey import DKeyed
32from jgdv.structs.dkey import ExpInst_d
33from jgdv._abstract.protocols.general import SpecStruct_p, Buildable_p
34# ##-- end 3rd party imports
35
36# ##-- 1st party imports
37import doot
38import doot.errors
39from doot.workflow.structs.task_name import TaskName
40
41# ##-- end 1st party imports
42
43# ##-- types
44# isort: off
45import abc
46import collections.abc
47from typing import TYPE_CHECKING, Generic, cast, assert_type, assert_never
48# Protocols:
49from typing import Protocol, runtime_checkable
50# Typing Decorators:
51from typing import no_type_check, final, override, overload
52
53if TYPE_CHECKING:
54 from jgdv import Maybe, Ident, Method, Func, Decorator
55 from typing import Final
56 from typing import ClassVar, Any, LiteralString
57 from typing import Never, Self, Literal
58 from typing import TypeGuard
59 from collections.abc import Iterable, Iterator, Callable, Generator
60 from collections.abc import Sequence, Mapping, MutableMapping, Hashable
61
62 from jgdv.structs.dkey import Key_p
63 from jgdv.structs.dkey._util._interface import SourceChain_d, InstructionFactory_p, ExpOpts, ExpInstChain_d
64
65# isort: on
66# ##-- end types
67
68##-- logging
69logging = logmod.getLogger(__name__)
70##-- end logging
71
72##--| Vars
73STATE_TASK_NAME_K = doot.constants.patterns.STATE_TASK_NAME_K # type: ignore[attr-defined]
74##--|
75
[docs]
76class TaskNameDKey(DKey, mark=TaskName, convert="t"):
77 __slots__ = ()
78
79 def __init__(self, *args:Any, **kwargs:Any) -> None:
80 super().__init__(*args, **kwargs)
81 self.data.expansion_type = TaskName
82 self.data.typecheck = TaskName
83
[docs]
84class DootPathDKey(DKey[pl.Path], mark=pl.Path, ctor=pl.Path, convert="p", overwrite=True):
85 """
86 A MultiKey that always expands as a path,
87 eg: `{temp}/{name}.log`
88 """
89 __slots__ = ("_relative",)
90 _extra_kwargs : ClassVar[set[str]] = {"relative"}
91
92 def __init__(self, *args:Any, **kwargs:Any) -> None:
93 super().__init__(*args, **kwargs)
94 self.data.expansion_type = pl.Path
95 self.data.typecheck = pl.Path
96 self._relative = kwargs.get('relative', False)
97
[docs]
98 def _multi(self) -> Literal[True]:
99 return True
100
103
[docs]
104 def exp_final_h(self, inst:ExpInst_d, root:Maybe[ExpInst_d], factory:InstructionFactory_p, opts:dict) -> Maybe[ExpInst_d]:
105 relative = opts.get("relative", False)
106 match inst:
107 case ExpInst_d(value=pl.Path() as x) if relative and x.is_absolute():
108 as_relative = x.relative_to(doot.locs.root)
109 return factory.literal_inst(as_relative)
110 case ExpInst_d(value=pl.Path()) as x if relative:
111 return x
112 case ExpInst_d(value=pl.Path() as x) as v:
113 logging.debug("Normalizing Single Path Key: %s", x)
114 normed = doot.locs.Current.normalize(x) # type: ignore[attr-defined]
115 return factory.literal_inst(normed)
116 case x:
117 raise TypeError("Path Expansion did not produce a path", x)
118
[docs]
119class DootKeyed(DecoratorAccessor_m, DKeyed):
120 """ Extends jgdv.structs.dkey.DKeyed to handle additional decoration types
121 specific for doot
122 """
123 _decoration_builder : ClassVar[type] = DKeyExpansionDecorator
124
[docs]
125 @classmethod
126 def taskname(cls, fn:Callable) -> Decorator:
127 keys = [DKey[TaskName](STATE_TASK_NAME_K, implicit=True)]
128 dec = cls._build_decorator(keys)
129 result = dec(fn)
130 return result