Source code for jgdv.structs.chainguard.mixins.access_m

  1#!/usr/bin/env python3
  2"""
  3
  4"""
  5
  6# Imports:
  7from __future__ import annotations
  8
  9# ##-- stdlib imports
 10import collections
 11import contextlib
 12import datetime
 13import enum
 14import faulthandler
 15import functools as ftz
 16import hashlib
 17import itertools as itz
 18import logging as logmod
 19import pathlib as pl
 20import re
 21import time
 22import types
 23import weakref
 24from copy import deepcopy
 25from dataclasses import InitVar, dataclass, field
 26from time import sleep
 27from uuid import UUID, uuid1
 28from weakref import ref
 29
 30# ##-- end stdlib imports
 31
 32# ##-- 1st party imports
 33from jgdv.structs.chainguard.errors import GuardedAccessError
 34
 35# ##-- end 1st party imports
 36
 37# ##-- types
 38# isort: off
 39import abc
 40import collections.abc
 41from typing import TYPE_CHECKING, cast, assert_type, assert_never
 42from typing import Generic, NewType
 43# Protocols:
 44from typing import Protocol, runtime_checkable
 45# Typing Decorators:
 46from typing import no_type_check, final, override, overload
 47
 48if TYPE_CHECKING:
 49    from jgdv import Maybe
 50    from typing import Final
 51    from typing import ClassVar, Any, LiteralString
 52    from typing import Never, Self, Literal
 53    from typing import TypeGuard
 54    from collections.abc import Iterable, Iterator, Callable, Generator
 55    from collections.abc import Sequence, Mapping, MutableMapping, Hashable
 56
 57    from .._interface import ChainGuard_i, TomlTypes
 58    from .._base import GuardBase
 59# isort: on
 60# ##-- end types
 61
 62##-- logging
 63logging = logmod.getLogger(__name__)
 64##-- end logging
 65
 66super_get             = object.__getattribute__
 67super_set             = object.__setattr__
 68USCORE   : Final[str] = "_"
 69DASH     : Final[str] = "-"
 70MUTABLE  : Final[str] = "__mutable"
 71##--|
 72
[docs] 73class TomlAccess_m: 74 """ Mixing for dynamic attribute access """ 75 76 @override 77 def __setattr__(self:ChainGuard_i, attr:str, value:Any) -> None: 78 if not getattr(self, MUTABLE): 79 raise TypeError() 80 super_set(self, attr, value) 81 82 def __getattr__(self:ChainGuard_i, attr:str) -> Any: # noqa: ANN401 83 index : list[str] 84 index_s : str 85 table : dict = self._table() # type: ignore[operator,assignment] 86 87 if attr not in table and attr.replace(USCORE, DASH) not in table: 88 index = [*self._index(), attr] # type: ignore[operator,misc] 89 index_s = ".".join(index) 90 available = " ".join(self.keys()) 91 msg = f"{index_s} not found, available: [{available}]" 92 raise GuardedAccessError(msg) 93 94 match table.get(attr, None) or table.get(attr.replace(USCORE, DASH), None): 95 case dict() as result: 96 return type(self)(result, index=[*self._index(), attr]) 97 case list() as result if all(isinstance(x, dict) for x in result): 98 index = self._index() 99 return [type(self)(x, index=index[:]) for x in result if isinstance(x, dict)] 100 case _ as result: 101 return result 102 103 def __getitem__(self:ChainGuard_i, keys:str|list[str]|tuple[str]) -> Any: # noqa: ANN401 104 curr : ChainGuard_i|TomlTypes = self 105 match keys: 106 case tuple(): 107 for key in keys: 108 curr = getattr(curr, key) 109 case str(): 110 curr = getattr(self, keys) 111 case _: 112 pass 113 114 return curr 115
[docs] 116 def get(self:ChainGuard_i, key:str, default:Maybe=None) -> Maybe: 117 if key in self: 118 return self[key] 119 120 return default