Source code for jgdv.structs.strang.formatter

  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
 26import sh
 27
 28# ##-- end 3rd party imports
 29
 30# ##-- 1st party imports
 31from jgdv import Mixin
 32from jgdv._abstract.protocols.general import SpecStruct_p
 33
 34# ##-- end 1st party imports
 35
 36from . import _interface as API  # noqa: N812
 37from . import errors
 38
 39# ##-- types
 40# isort: off
 41import abc
 42import collections.abc
 43from typing import TYPE_CHECKING, Generic, cast, assert_type, assert_never
 44# Protocols:
 45from typing import Protocol, runtime_checkable
 46# Typing Decorators:
 47from typing import no_type_check, final, override, overload
 48
 49if TYPE_CHECKING:
 50    from jgdv import Maybe
 51    from jgdv import Ident, FmtStr, Rx, RxStr, Func
 52    from typing import Final
 53    from typing import ClassVar, Any, LiteralString
 54    from typing import Never, Self, Literal
 55    from typing import TypeGuard
 56    from collections.abc import Iterable, Iterator, Callable, Generator
 57    from collections.abc import Sequence, Mapping, MutableMapping, Hashable
 58
 59    from ._interface import Strang_p
 60
 61# isort: on
 62# ##-- end types
 63
 64##-- logging
 65logging = logmod.getLogger(__file__)
 66##-- end logging
 67
[docs] 68class StrangFormatter(string.Formatter): 69 """ 70 An Expander/Formatter to extend string formatting with options useful for dkey's 71 and doot specs/state. 72 73 """ 74
[docs] 75 def format(self, key:str, /, *args:Any, **kwargs:Any) -> str: # noqa: ANN401 76 """ format keys as strings """ 77 match key: 78 case str(): 79 fmt = key 80 case pl.Path(): 81 raise NotImplementedError() 82 case _: 83 raise TypeError(errors.FormatterExpansionTypeFail, key) 84 85 result = self.vformat(fmt, args, kwargs) 86 return result
87
[docs] 88 def get_value(self, key:int|str, args:Sequence[Any], kwargs:Any) -> str: # noqa: ANN401 89 """ lowest level handling of keys being expanded """ 90 # This handles when the key is something like '1968' 91 if isinstance(key, int) and 0 <= key <= len(args): 92 return args[key] 93 94 return kwargs.get(key, key)
95
[docs] 96 def convert_field(self, value:str, conversion:Maybe[str]) -> str: 97 # do any conversion on the resulting object 98 match conversion: 99 case None: 100 return value 101 case "s" | "p" | "R" | "c" | "t": 102 return str(value) 103 case "r": 104 return repr(value) 105 case "a": 106 return ascii(value) 107 case _: 108 raise ValueError(errors.FormatterConversionUnknownSpec.format(spec=conversion))
109
[docs] 110 def expanded_str(self, value:Strang_p, *, stop:Maybe[int]=None) -> str: 111 """ Create a str with generative marks replaced with generated values 112 113 eg: a.b.c.<gen-uuid> -> a.b.c.<UUID:......> 114 """ 115 raise NotImplementedError()
116
[docs] 117 def format_subval(self, value:Strang_p, val:str, *, no_expansion:bool=False) -> str: 118 match val: 119 case str(): 120 return val 121 case UUID() if no_expansion: 122 return "<uuid>" 123 case UUID(): 124 return f"<uuid:{val}>" 125 case _: 126 raise TypeError(errors.FormatterUnkownBodyType, val)