omlish 0.0.0.dev423__py3-none-any.whl → 0.0.0.dev425__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- omlish/__about__.py +3 -3
- omlish/dataclasses/impl/configs.py +2 -1
- omlish/formats/json/stream/lexing.py +8 -0
- omlish/formats/json/stream/utils.py +3 -0
- omlish/formats/json5/streams.py +22 -0
- omlish/lang/__init__.py +3 -1
- omlish/lang/asyncs.py +12 -0
- omlish/lang/functions.py +0 -11
- omlish/lang/lazyglobals.py +27 -5
- omlish/lang/maysync.py +2 -2
- omlish/lifecycles/contextmanagers.py +1 -2
- omlish/lifecycles/controller.py +1 -2
- omlish/lite/asyncs.py +15 -0
- omlish/lite/timing.py +2 -2
- omlish/logs/all.py +23 -34
- omlish/logs/base.py +248 -0
- omlish/logs/callers.py +21 -15
- omlish/logs/infos.py +105 -0
- omlish/logs/levels.py +64 -0
- omlish/logs/protocols.py +31 -0
- omlish/logs/standard.py +12 -11
- omlish/logs/std/adapters.py +41 -0
- omlish/logs/std/configs.py +29 -0
- omlish/logs/{filters.py → std/filters.py} +1 -1
- omlish/logs/{handlers.py → std/handlers.py} +1 -1
- omlish/logs/{json.py → std/json.py} +2 -2
- omlish/logs/{proxy.py → std/proxy.py} +3 -3
- omlish/logs/std/records.py +286 -0
- omlish/logs/times.py +89 -0
- omlish/logs/typed/bindings.py +24 -0
- omlish/logs/utils.py +60 -4
- omlish/logs/warnings.py +8 -0
- omlish/manifests/loading.py +1 -1
- omlish/os/journald.py +3 -3
- omlish/testing/pytest/plugins/skips.py +0 -4
- {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev425.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev425.dist-info}/RECORD +44 -86
- omlish/defs.py +0 -216
- omlish/dispatch/_dispatch2.py +0 -69
- omlish/dispatch/_dispatch3.py +0 -108
- omlish/dynamic.py +0 -219
- omlish/formats/json/Json.g4 +0 -77
- omlish/formats/json/_antlr/JsonLexer.py +0 -109
- omlish/formats/json/_antlr/JsonListener.py +0 -61
- omlish/formats/json/_antlr/JsonParser.py +0 -457
- omlish/formats/json/_antlr/JsonVisitor.py +0 -42
- omlish/io/trampoline.py +0 -289
- omlish/logs/abc.py +0 -319
- omlish/logs/color.py +0 -27
- omlish/logs/configs.py +0 -29
- omlish/logs/protocol.py +0 -218
- omlish/logs/timing.py +0 -58
- omlish/specs/irc/__init__.py +0 -0
- omlish/specs/irc/messages/__init__.py +0 -0
- omlish/specs/irc/messages/base.py +0 -49
- omlish/specs/irc/messages/formats.py +0 -92
- omlish/specs/irc/messages/messages.py +0 -774
- omlish/specs/irc/messages/parsing.py +0 -98
- omlish/specs/irc/numerics/__init__.py +0 -0
- omlish/specs/irc/numerics/formats.py +0 -97
- omlish/specs/irc/numerics/numerics.py +0 -865
- omlish/specs/irc/numerics/types.py +0 -59
- omlish/specs/irc/protocol/LICENSE +0 -11
- omlish/specs/irc/protocol/__init__.py +0 -61
- omlish/specs/irc/protocol/consts.py +0 -6
- omlish/specs/irc/protocol/errors.py +0 -30
- omlish/specs/irc/protocol/message.py +0 -21
- omlish/specs/irc/protocol/nuh.py +0 -55
- omlish/specs/irc/protocol/parsing.py +0 -158
- omlish/specs/irc/protocol/rendering.py +0 -153
- omlish/specs/irc/protocol/tags.py +0 -102
- omlish/specs/irc/protocol/utils.py +0 -30
- omlish/specs/proto/Protobuf3.g4 +0 -396
- omlish/specs/proto/__init__.py +0 -0
- omlish/specs/proto/_antlr/Protobuf3Lexer.py +0 -340
- omlish/specs/proto/_antlr/Protobuf3Listener.py +0 -448
- omlish/specs/proto/_antlr/Protobuf3Parser.py +0 -3909
- omlish/specs/proto/_antlr/Protobuf3Visitor.py +0 -257
- omlish/specs/proto/_antlr/__init__.py +0 -0
- omlish/specs/proto/nodes.py +0 -54
- omlish/specs/proto/parsing.py +0 -97
- omlish/sql/parsing/Minisql.g4 +0 -292
- omlish/sql/parsing/__init__.py +0 -0
- omlish/sql/parsing/_antlr/MinisqlLexer.py +0 -322
- omlish/sql/parsing/_antlr/MinisqlListener.py +0 -511
- omlish/sql/parsing/_antlr/MinisqlParser.py +0 -3763
- omlish/sql/parsing/_antlr/MinisqlVisitor.py +0 -292
- omlish/sql/parsing/_antlr/__init__.py +0 -0
- omlish/sql/parsing/parsing.py +0 -119
- /omlish/{.manifests.json → .omlish-manifests.json} +0 -0
- /omlish/{formats/json/_antlr → logs/std}/__init__.py +0 -0
- /omlish/logs/{noisy.py → std/noisy.py} +0 -0
- {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev425.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev425.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev425.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev425.dist-info}/top_level.txt +0 -0
omlish/logs/protocol.py
DELETED
@@ -1,218 +0,0 @@
|
|
1
|
-
# ruff: noqa: UP006 UP007 UP045
|
2
|
-
# @omlish-lite
|
3
|
-
import abc
|
4
|
-
import logging
|
5
|
-
import sys
|
6
|
-
import typing as ta
|
7
|
-
|
8
|
-
from .callers import LoggingCaller
|
9
|
-
from .levels import LogLevel
|
10
|
-
|
11
|
-
|
12
|
-
T = ta.TypeVar('T')
|
13
|
-
T_co = ta.TypeVar('T_co', covariant=True)
|
14
|
-
|
15
|
-
|
16
|
-
##
|
17
|
-
|
18
|
-
|
19
|
-
class AnyLogging(ta.Protocol[T_co]):
|
20
|
-
def isEnabledFor(self, level: LogLevel) -> bool: ... # noqa
|
21
|
-
|
22
|
-
def getEffectiveLevel(self) -> LogLevel: ... # noqa
|
23
|
-
|
24
|
-
#
|
25
|
-
|
26
|
-
def debug(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> T_co: ...
|
27
|
-
|
28
|
-
def info(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> T_co: ...
|
29
|
-
|
30
|
-
def warning(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> T_co: ...
|
31
|
-
|
32
|
-
def error(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> T_co: ...
|
33
|
-
|
34
|
-
def exception(self, msg: str, *args: ta.Any, exc_info: bool = True, **kwargs: ta.Any) -> T_co: ...
|
35
|
-
|
36
|
-
def critical(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> T_co: ...
|
37
|
-
|
38
|
-
def log(self, level: LogLevel, msg: str, *args: ta.Any, **kwargs: ta.Any) -> T_co: ...
|
39
|
-
|
40
|
-
|
41
|
-
class Logging(AnyLogging[None], ta.Protocol):
|
42
|
-
pass
|
43
|
-
|
44
|
-
|
45
|
-
class AsyncLogging(AnyLogging[ta.Awaitable[None]], ta.Protocol):
|
46
|
-
pass
|
47
|
-
|
48
|
-
|
49
|
-
##
|
50
|
-
|
51
|
-
|
52
|
-
class AnyAbstractLogging(abc.ABC, ta.Generic[T]):
|
53
|
-
@ta.final
|
54
|
-
def isEnabledFor(self, level: LogLevel) -> bool: # noqa
|
55
|
-
return self.is_enabled_for(level)
|
56
|
-
|
57
|
-
def is_enabled_for(self, level: LogLevel) -> bool: # noqa
|
58
|
-
return level >= self.getEffectiveLevel()
|
59
|
-
|
60
|
-
@ta.final
|
61
|
-
def getEffectiveLevel(self) -> LogLevel: # noqa
|
62
|
-
return self.get_effective_level()
|
63
|
-
|
64
|
-
@abc.abstractmethod
|
65
|
-
def get_effective_level(self) -> LogLevel: # noqa
|
66
|
-
raise NotImplementedError
|
67
|
-
|
68
|
-
#
|
69
|
-
|
70
|
-
def debug(self, msg: str, *args: ta.Any, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> T:
|
71
|
-
return self.log(logging.DEBUG, msg, *args, _logging_stack_offset=_logging_stack_offset + 1, **kwargs)
|
72
|
-
|
73
|
-
def info(self, msg: str, *args: ta.Any, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> T:
|
74
|
-
return self.log(logging.INFO, msg, *args, _logging_stack_offset=_logging_stack_offset + 1, **kwargs)
|
75
|
-
|
76
|
-
def warning(self, msg: str, *args: ta.Any, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> T:
|
77
|
-
return self.log(logging.WARNING, msg, *args, _logging_stack_offset=_logging_stack_offset + 1, **kwargs)
|
78
|
-
|
79
|
-
def error(self, msg: str, *args: ta.Any, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> T:
|
80
|
-
return self.log(logging.ERROR, msg, *args, _logging_stack_offset=_logging_stack_offset + 1, **kwargs)
|
81
|
-
|
82
|
-
def exception(self, msg: str, *args: ta.Any, exc_info: bool = True, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> T: # noqa
|
83
|
-
return self.error(msg, *args, exc_info=exc_info, _logging_stack_offset=_logging_stack_offset + 1, **kwargs) # noqa
|
84
|
-
|
85
|
-
def critical(self, msg: str, *args: ta.Any, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> T:
|
86
|
-
return self.log(logging.CRITICAL, msg, *args, _logging_stack_offset=_logging_stack_offset + 1, **kwargs)
|
87
|
-
|
88
|
-
@abc.abstractmethod
|
89
|
-
def log(
|
90
|
-
self,
|
91
|
-
level: int,
|
92
|
-
msg: str,
|
93
|
-
*args: ta.Any,
|
94
|
-
exc_info: ta.Any = None,
|
95
|
-
extra: ta.Any = None,
|
96
|
-
stack_info: bool = False,
|
97
|
-
_logging_stack_offset: int = 0,
|
98
|
-
) -> T:
|
99
|
-
raise NotImplementedError
|
100
|
-
|
101
|
-
|
102
|
-
class AbstractLogging(AnyAbstractLogging[None], abc.ABC):
|
103
|
-
def log(self, level: LogLevel, msg: str, *args: ta.Any, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> None:
|
104
|
-
if not isinstance(level, int):
|
105
|
-
raise TypeError('Level must be an integer.')
|
106
|
-
if self.is_enabled_for(level):
|
107
|
-
self._log(level, msg, args, _logging_stack_offset=_logging_stack_offset + 1, **kwargs)
|
108
|
-
|
109
|
-
@abc.abstractmethod
|
110
|
-
def _log(
|
111
|
-
self,
|
112
|
-
level: int,
|
113
|
-
msg: str,
|
114
|
-
args: ta.Any,
|
115
|
-
*,
|
116
|
-
exc_info: ta.Any = None,
|
117
|
-
extra: ta.Any = None,
|
118
|
-
stack_info: bool = False,
|
119
|
-
_logging_stack_offset: int = 0,
|
120
|
-
) -> None:
|
121
|
-
raise NotImplementedError
|
122
|
-
|
123
|
-
|
124
|
-
class AbstractAsyncLogging(AnyAbstractLogging[ta.Awaitable[None]], abc.ABC):
|
125
|
-
async def log(self, level: LogLevel, msg: str, *args: ta.Any, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> None: # noqa
|
126
|
-
if not isinstance(level, int):
|
127
|
-
raise TypeError('Level must be an integer.')
|
128
|
-
if self.is_enabled_for(level):
|
129
|
-
await self._log(level, msg, args, _logging_stack_offset=_logging_stack_offset + 1, **kwargs)
|
130
|
-
|
131
|
-
@abc.abstractmethod
|
132
|
-
def _log(
|
133
|
-
self,
|
134
|
-
level: int,
|
135
|
-
msg: str,
|
136
|
-
args: ta.Any,
|
137
|
-
*,
|
138
|
-
exc_info: ta.Any = None,
|
139
|
-
extra: ta.Any = None,
|
140
|
-
stack_info: bool = False,
|
141
|
-
_logging_stack_offset: int = 0,
|
142
|
-
) -> ta.Awaitable[None]:
|
143
|
-
raise NotImplementedError
|
144
|
-
|
145
|
-
|
146
|
-
##
|
147
|
-
|
148
|
-
|
149
|
-
class AnyNopLogging(AnyAbstractLogging[T], abc.ABC):
|
150
|
-
def get_effective_level(self) -> LogLevel:
|
151
|
-
return logging.CRITICAL + 1
|
152
|
-
|
153
|
-
|
154
|
-
class NopLogging(AnyNopLogging[None], AbstractLogging):
|
155
|
-
def _log(self, *args: ta.Any, **kwargs: ta.Any) -> None:
|
156
|
-
pass
|
157
|
-
|
158
|
-
|
159
|
-
class NopAsyncLogging(AnyNopLogging[ta.Awaitable[None]], AbstractAsyncLogging):
|
160
|
-
async def _log(self, *args: ta.Any, **kwargs: ta.Any) -> None:
|
161
|
-
pass
|
162
|
-
|
163
|
-
|
164
|
-
##
|
165
|
-
|
166
|
-
|
167
|
-
class StdlibLogging(AbstractLogging):
|
168
|
-
def __init__(self, underlying: logging.Logger) -> None:
|
169
|
-
super().__init__()
|
170
|
-
|
171
|
-
if not isinstance(underlying, logging.Logger):
|
172
|
-
raise TypeError(underlying)
|
173
|
-
|
174
|
-
self._underlying = underlying
|
175
|
-
|
176
|
-
#
|
177
|
-
|
178
|
-
def is_enabled_for(self, level: int) -> bool: # noqa
|
179
|
-
return self._underlying.isEnabledFor(level)
|
180
|
-
|
181
|
-
def get_effective_level(self) -> int: # noqa
|
182
|
-
return self._underlying.getEffectiveLevel()
|
183
|
-
|
184
|
-
#
|
185
|
-
|
186
|
-
def _log(
|
187
|
-
self,
|
188
|
-
level: int,
|
189
|
-
msg: str,
|
190
|
-
args: ta.Any,
|
191
|
-
*,
|
192
|
-
exc_info: ta.Any = None,
|
193
|
-
extra: ta.Any = None,
|
194
|
-
stack_info: bool = False,
|
195
|
-
_logging_stack_offset: int = 0,
|
196
|
-
) -> None:
|
197
|
-
caller = LoggingCaller.find(_logging_stack_offset, stack_info=stack_info)
|
198
|
-
|
199
|
-
if exc_info:
|
200
|
-
if isinstance(exc_info, BaseException):
|
201
|
-
exc_info = (type(exc_info), exc_info, exc_info.__traceback__)
|
202
|
-
elif not isinstance(exc_info, tuple):
|
203
|
-
exc_info = sys.exc_info()
|
204
|
-
|
205
|
-
record = self._underlying.makeRecord(
|
206
|
-
name=self._underlying.name,
|
207
|
-
level=level,
|
208
|
-
fn=caller.filename,
|
209
|
-
lno=caller.lineno,
|
210
|
-
msg=msg,
|
211
|
-
args=args,
|
212
|
-
exc_info=exc_info,
|
213
|
-
func=caller.func,
|
214
|
-
extra=extra,
|
215
|
-
sinfo=caller.sinfo,
|
216
|
-
)
|
217
|
-
|
218
|
-
self._underlying.handle(record)
|
omlish/logs/timing.py
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
# ruff: noqa: UP006 UP007 UP045
|
2
|
-
# @omlish-lite
|
3
|
-
import logging
|
4
|
-
import time
|
5
|
-
import typing as ta
|
6
|
-
|
7
|
-
|
8
|
-
##
|
9
|
-
|
10
|
-
|
11
|
-
class LogTimingContext:
|
12
|
-
DEFAULT_LOG: ta.ClassVar[ta.Optional[logging.Logger]] = None
|
13
|
-
|
14
|
-
class _NOT_SPECIFIED: # noqa
|
15
|
-
def __new__(cls, *args, **kwargs): # noqa
|
16
|
-
raise TypeError
|
17
|
-
|
18
|
-
def __init__(
|
19
|
-
self,
|
20
|
-
description: str,
|
21
|
-
*,
|
22
|
-
log: ta.Union[logging.Logger, ta.Type[_NOT_SPECIFIED], None] = _NOT_SPECIFIED, # noqa
|
23
|
-
level: int = logging.DEBUG,
|
24
|
-
) -> None:
|
25
|
-
super().__init__()
|
26
|
-
|
27
|
-
self._description = description
|
28
|
-
if log is self._NOT_SPECIFIED:
|
29
|
-
log = self.DEFAULT_LOG # noqa
|
30
|
-
self._log: ta.Optional[logging.Logger] = log # type: ignore
|
31
|
-
self._level = level
|
32
|
-
|
33
|
-
def set_description(self, description: str) -> 'LogTimingContext':
|
34
|
-
self._description = description
|
35
|
-
return self
|
36
|
-
|
37
|
-
_begin_time: float
|
38
|
-
_end_time: float
|
39
|
-
|
40
|
-
def __enter__(self) -> 'LogTimingContext':
|
41
|
-
self._begin_time = time.time()
|
42
|
-
|
43
|
-
if self._log is not None:
|
44
|
-
self._log.log(self._level, f'Begin : {self._description}') # noqa
|
45
|
-
|
46
|
-
return self
|
47
|
-
|
48
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
49
|
-
self._end_time = time.time()
|
50
|
-
|
51
|
-
if self._log is not None:
|
52
|
-
self._log.log(
|
53
|
-
self._level,
|
54
|
-
f'End : {self._description} - {self._end_time - self._begin_time:0.2f} s elapsed',
|
55
|
-
)
|
56
|
-
|
57
|
-
|
58
|
-
log_timing_context = LogTimingContext
|
omlish/specs/irc/__init__.py
DELETED
File without changes
|
File without changes
|
@@ -1,49 +0,0 @@
|
|
1
|
-
import typing as ta
|
2
|
-
|
3
|
-
from .... import check
|
4
|
-
from .... import dataclasses as dc
|
5
|
-
from ....funcs import pairs as fps
|
6
|
-
from ..numerics import numerics as nr
|
7
|
-
from .formats import MessageFormat
|
8
|
-
from .formats import MessageParamsUnpacker
|
9
|
-
|
10
|
-
|
11
|
-
##
|
12
|
-
|
13
|
-
|
14
|
-
class Message(dc.Case):
|
15
|
-
FORMAT: ta.ClassVar[MessageFormat]
|
16
|
-
REPLIES: ta.ClassVar[ta.Collection[nr.NumericReply]] = ()
|
17
|
-
|
18
|
-
|
19
|
-
##
|
20
|
-
|
21
|
-
|
22
|
-
def list_pair_params_unpacker(
|
23
|
-
kwarg: str,
|
24
|
-
key_param: str,
|
25
|
-
value_param: str,
|
26
|
-
) -> MessageParamsUnpacker:
|
27
|
-
def forward(params: ta.Mapping[str, str]) -> ta.Mapping[str, ta.Any]:
|
28
|
-
out: dict = dict(params)
|
29
|
-
ks = out.pop(key_param)
|
30
|
-
vs = out.pop(value_param, None)
|
31
|
-
if vs is not None:
|
32
|
-
out[kwarg] = list(zip(ks, vs, strict=True))
|
33
|
-
else:
|
34
|
-
out[kwarg] = ks
|
35
|
-
return out
|
36
|
-
|
37
|
-
def backward(kwargs: ta.Mapping[str, ta.Any]) -> ta.Mapping[str, str]:
|
38
|
-
out: dict = dict(kwargs)
|
39
|
-
ts = out.pop(kwarg)
|
40
|
-
is_ts = check.single({isinstance(e, tuple) for e in ts})
|
41
|
-
if is_ts:
|
42
|
-
ks, vs = zip(*ts)
|
43
|
-
out[key_param] = ks
|
44
|
-
out[value_param] = vs
|
45
|
-
else:
|
46
|
-
out[key_param] = ts
|
47
|
-
return out
|
48
|
-
|
49
|
-
return fps.of(forward, backward)
|
@@ -1,92 +0,0 @@
|
|
1
|
-
import enum
|
2
|
-
import typing as ta
|
3
|
-
|
4
|
-
from .... import check
|
5
|
-
from .... import dataclasses as dc
|
6
|
-
from .... import lang
|
7
|
-
from ....funcs import pairs as fps
|
8
|
-
|
9
|
-
|
10
|
-
MessageParamsUnpacker: ta.TypeAlias = fps.FnPair[
|
11
|
-
ta.Mapping[str, str], # params
|
12
|
-
ta.Mapping[str, ta.Any], # kwargs
|
13
|
-
]
|
14
|
-
|
15
|
-
|
16
|
-
##
|
17
|
-
|
18
|
-
|
19
|
-
class MessageFormat(dc.Frozen, final=True):
|
20
|
-
name: str
|
21
|
-
|
22
|
-
class Param(dc.Case):
|
23
|
-
@classmethod
|
24
|
-
def of(cls, obj: ta.Any) -> 'MessageFormat.Param':
|
25
|
-
if isinstance(obj, MessageFormat.Param):
|
26
|
-
return obj
|
27
|
-
|
28
|
-
elif isinstance(obj, str):
|
29
|
-
s = check.non_empty_str(obj)
|
30
|
-
|
31
|
-
optional = False
|
32
|
-
if s.startswith('?'):
|
33
|
-
optional = True
|
34
|
-
s = s[1:]
|
35
|
-
|
36
|
-
arity = MessageFormat.KwargParam.Arity.SINGLE
|
37
|
-
if s.startswith('*'):
|
38
|
-
arity = MessageFormat.KwargParam.Arity.VARIADIC
|
39
|
-
s = s[1:]
|
40
|
-
|
41
|
-
elif s.startswith(','):
|
42
|
-
arity = MessageFormat.KwargParam.Arity.COMMA_LIST
|
43
|
-
s = s[1:]
|
44
|
-
|
45
|
-
return MessageFormat.KwargParam(
|
46
|
-
s,
|
47
|
-
optional=optional,
|
48
|
-
arity=arity,
|
49
|
-
)
|
50
|
-
|
51
|
-
else:
|
52
|
-
raise TypeError(obj)
|
53
|
-
|
54
|
-
class KwargParam(Param):
|
55
|
-
name: str = dc.xfield(validate=lang.is_ident)
|
56
|
-
|
57
|
-
optional: bool = False
|
58
|
-
|
59
|
-
class Arity(enum.Enum):
|
60
|
-
SINGLE = enum.auto() # <foo>
|
61
|
-
VARIADIC = enum.auto() # <foo>{ <foo>}
|
62
|
-
COMMA_LIST = enum.auto() # <foo>{,<foo>}
|
63
|
-
|
64
|
-
arity: Arity = Arity.SINGLE
|
65
|
-
|
66
|
-
class LiteralParam(Param):
|
67
|
-
text: str
|
68
|
-
|
69
|
-
params: ta.Sequence[Param]
|
70
|
-
|
71
|
-
_: dc.KW_ONLY
|
72
|
-
|
73
|
-
unpack_params: MessageParamsUnpacker | None = None
|
74
|
-
|
75
|
-
@dc.init
|
76
|
-
def _validate_params(self) -> None:
|
77
|
-
kws = [p for p in self.params if isinstance(p, MessageFormat.KwargParam)]
|
78
|
-
check.unique(p.name for p in kws)
|
79
|
-
check.state(all(p.arity is not MessageFormat.KwargParam.Arity.VARIADIC for p in kws[:-1]))
|
80
|
-
|
81
|
-
@classmethod
|
82
|
-
def of(
|
83
|
-
cls,
|
84
|
-
name: str,
|
85
|
-
*params: ta.Any,
|
86
|
-
**kwargs: ta.Any,
|
87
|
-
) -> 'MessageFormat':
|
88
|
-
return cls(
|
89
|
-
name,
|
90
|
-
[MessageFormat.Param.of(p) for p in params],
|
91
|
-
**kwargs,
|
92
|
-
)
|