Source code for jgdv.structs.strang._meta
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 re
15import time
16import types
17import collections
18import contextlib
19import hashlib
20from copy import deepcopy
21from uuid import UUID, uuid1
22from weakref import ref
23import atexit # for @atexit.register
24import faulthandler
25# ##-- end stdlib imports
26
27from . import errors
28
29# ##-- types
30# isort: off
31import abc
32import collections.abc
33import typing
34from typing import TYPE_CHECKING, cast, assert_type, assert_never
35from typing import Generic, NewType, Never
36# Protocols:
37from typing import Protocol, runtime_checkable
38# Typing Decorators:
39from typing import no_type_check, final, override, overload
40
41if TYPE_CHECKING:
42 import pathlib as pl
43 from jgdv import Maybe
44 from typing import Final
45 from typing import ClassVar, Any, LiteralString
46 from typing import Self, Literal
47 from typing import TypeGuard
48 from collections.abc import Iterable, Iterator, Callable, Generator
49 from collections.abc import Sequence, Mapping, MutableMapping, Hashable
50
51 from ._interface import Strang_p
52 from jgdv._abstract.protocols.pre_processable import PreProcessor_p, PreProcessResult, InstanceData, PostInstanceData
53##--|
54
55# isort: on
56# ##-- end types
57
58##-- logging
59logging = logmod.getLogger(__name__)
60##-- end logging
61
62# Vars:
63StrMeta : Final[type] = type(str)
64HasDictFail : Final[str] = "The resulting strang has a __dict__. Set the subclass to have __slots__=()"
65# Body:
66
[docs]
67class StrangMeta(StrMeta):
68 """ A Metaclass for Strang
69 It runs the pre-processsing and post-processing on the constructed str
70 to turn it into a strang
71 """
72
73 def __call__[T:Strang_p](cls:type[T], text:str|pl.Path, *args:Any, **kwargs:Any) -> Strang_p: # noqa: ANN401, N805
74 """ Overrides normal str creation to allow passing args to init """
75 ctor : type[T]
76 obj : T
77 processor : PreProcessor_p[T] = cls._processor
78 stage : str = "Pre-Process"
79
80 try:
81 text, inst_data, post_data, new_ctor = processor.pre_process(cls,
82 text,
83 *args,
84 strict=kwargs.pop("strict", False),
85 **kwargs,
86 )
87 ctor = new_ctor or cls
88 assert(isinstance(ctor, type|typing.GenericAlias)), ctor # type: ignore[attr-defined]
89 stage = "__new__"
90 obj = ctor.__new__(ctor, text)
91 stage = "__init__"
92 obj.__init__(*args, **collections.ChainMap(inst_data, kwargs)) # type: ignore[misc]
93 stage = "Process"
94 obj = processor.process(obj, data=post_data) or obj
95 stage = "Post-Process"
96 obj = processor.post_process(obj, data=post_data) or obj
97 except TypeError as err:
98 raise errors.StrangError(errors.StrangCtorFailure.format(cls=cls.__name__, stage=stage),
99 err, text, cls, processor) from None
100 except ValueError as err:
101 raise errors.StrangError(errors.StrangCtorFailure.format(cls=cls.__name__, stage=stage),
102 err, text, cls, processor) from None
103 else:
104 assert(isinstance(obj, str))
105 if hasattr(obj, "__dict__"):
106 raise ValueError(HasDictFail, type(obj))
107 return obj
108