omextra 0.0.0.dev472__py3-none-any.whl → 0.0.0.dev485__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.
- omextra/__about__.py +2 -0
- omextra/collections/__init__.py +0 -0
- omextra/collections/hamt/LICENSE +35 -0
- omextra/collections/hamt/__init__.py +0 -0
- omextra/collections/hamt/_hamt.c +3621 -0
- omextra/formats/goyaml/LICENSE +16 -0
- omextra/formats/goyaml/__init__.py +29 -0
- omextra/formats/goyaml/ast.py +2217 -0
- omextra/formats/goyaml/errors.py +49 -0
- omextra/formats/goyaml/parsing.py +2332 -0
- omextra/formats/goyaml/scanning.py +1888 -0
- omextra/formats/goyaml/tokens.py +998 -0
- omextra/text/abnf/LICENSE +16 -0
- omextra/text/abnf/__init__.py +79 -0
- omextra/text/abnf/base.py +313 -0
- omextra/text/abnf/core.py +141 -0
- omextra/text/abnf/errors.py +10 -0
- omextra/text/abnf/meta.py +583 -0
- omextra/text/abnf/parsers.py +343 -0
- omextra/text/abnf/utils.py +76 -0
- omextra/text/abnf/visitors.py +55 -0
- {omextra-0.0.0.dev472.dist-info → omextra-0.0.0.dev485.dist-info}/METADATA +2 -2
- {omextra-0.0.0.dev472.dist-info → omextra-0.0.0.dev485.dist-info}/RECORD +27 -7
- {omextra-0.0.0.dev472.dist-info → omextra-0.0.0.dev485.dist-info}/WHEEL +0 -0
- {omextra-0.0.0.dev472.dist-info → omextra-0.0.0.dev485.dist-info}/entry_points.txt +0 -0
- {omextra-0.0.0.dev472.dist-info → omextra-0.0.0.dev485.dist-info}/licenses/LICENSE +0 -0
- {omextra-0.0.0.dev472.dist-info → omextra-0.0.0.dev485.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,998 @@
|
|
|
1
|
+
# ruff: noqa: UP006 UP007 UP043 UP045
|
|
2
|
+
# @omlish-lite
|
|
3
|
+
import copy
|
|
4
|
+
import dataclasses as dc
|
|
5
|
+
import datetime
|
|
6
|
+
import enum
|
|
7
|
+
import functools
|
|
8
|
+
import typing as ta
|
|
9
|
+
|
|
10
|
+
from omlish.lite.dataclasses import dataclass_field_required
|
|
11
|
+
|
|
12
|
+
from .errors import YamlError
|
|
13
|
+
from .errors import YamlErrorOr
|
|
14
|
+
from .errors import yaml_error
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class YamlChars:
|
|
21
|
+
# SEQUENCE_ENTRY character for sequence entry
|
|
22
|
+
SEQUENCE_ENTRY = '-'
|
|
23
|
+
# MAPPING_KEY character for mapping key
|
|
24
|
+
MAPPING_KEY = '?'
|
|
25
|
+
# MAPPING_VALUE character for mapping value
|
|
26
|
+
MAPPING_VALUE = ':'
|
|
27
|
+
# COLLECT_ENTRY character for collect entry
|
|
28
|
+
COLLECT_ENTRY = ','
|
|
29
|
+
# SEQUENCE_START character for sequence start
|
|
30
|
+
SEQUENCE_START = '['
|
|
31
|
+
# SEQUENCE_END character for sequence end
|
|
32
|
+
SEQUENCE_END = ']'
|
|
33
|
+
# MAPPING_START character for mapping start
|
|
34
|
+
MAPPING_START = '{'
|
|
35
|
+
# MAPPING_END character for mapping end
|
|
36
|
+
MAPPING_END = '}'
|
|
37
|
+
# COMMENT character for comment
|
|
38
|
+
COMMENT = '#'
|
|
39
|
+
# ANCHOR character for anchor
|
|
40
|
+
ANCHOR = '&'
|
|
41
|
+
# ALIAS character for alias
|
|
42
|
+
ALIAS = '*'
|
|
43
|
+
# TAG character for tag
|
|
44
|
+
TAG = '!'
|
|
45
|
+
# LITERAL character for literal
|
|
46
|
+
LITERAL = '|'
|
|
47
|
+
# FOLDED character for folded
|
|
48
|
+
FOLDED = '>'
|
|
49
|
+
# SINGLE_QUOTE character for single quote
|
|
50
|
+
SINGLE_QUOTE = '\''
|
|
51
|
+
# DOUBLE_QUOTE character for double quote
|
|
52
|
+
DOUBLE_QUOTE = '"'
|
|
53
|
+
# DIRECTIVE character for directive
|
|
54
|
+
DIRECTIVE = '%'
|
|
55
|
+
# SPACE character for space
|
|
56
|
+
SPACE = ' '
|
|
57
|
+
# LINE_BREAK character for line break
|
|
58
|
+
LINE_BREAK = '\n'
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class YamlTokenType(enum.Enum):
|
|
62
|
+
# UNKNOWN reserve for invalid type
|
|
63
|
+
UNKNOWN = enum.auto()
|
|
64
|
+
# DOCUMENT_HEADER type for DocumentHeader token
|
|
65
|
+
DOCUMENT_HEADER = enum.auto()
|
|
66
|
+
# DOCUMENT_END type for DocumentEnd token
|
|
67
|
+
DOCUMENT_END = enum.auto()
|
|
68
|
+
# SEQUENCE_ENTRY type for SequenceEntry token
|
|
69
|
+
SEQUENCE_ENTRY = enum.auto()
|
|
70
|
+
# MAPPING_KEY type for MappingKey token
|
|
71
|
+
MAPPING_KEY = enum.auto()
|
|
72
|
+
# MAPPING_VALUE type for MappingValue token
|
|
73
|
+
MAPPING_VALUE = enum.auto()
|
|
74
|
+
# MERGE_KEY type for MergeKey token
|
|
75
|
+
MERGE_KEY = enum.auto()
|
|
76
|
+
# COLLECT_ENTRY type for CollectEntry token
|
|
77
|
+
COLLECT_ENTRY = enum.auto()
|
|
78
|
+
# SEQUENCE_START type for SequenceStart token
|
|
79
|
+
SEQUENCE_START = enum.auto()
|
|
80
|
+
# SEQUENCE_END type for SequenceEnd token
|
|
81
|
+
SEQUENCE_END = enum.auto()
|
|
82
|
+
# MAPPING_START type for MappingStart token
|
|
83
|
+
MAPPING_START = enum.auto()
|
|
84
|
+
# MAPPING_END type for MappingEnd token
|
|
85
|
+
MAPPING_END = enum.auto()
|
|
86
|
+
# COMMENT type for Comment token
|
|
87
|
+
COMMENT = enum.auto()
|
|
88
|
+
# ANCHOR type for Anchor token
|
|
89
|
+
ANCHOR = enum.auto()
|
|
90
|
+
# ALIAS type for Alias token
|
|
91
|
+
ALIAS = enum.auto()
|
|
92
|
+
# TAG type for Tag token
|
|
93
|
+
TAG = enum.auto()
|
|
94
|
+
# LITERAL type for Literal token
|
|
95
|
+
LITERAL = enum.auto()
|
|
96
|
+
# FOLDED type for Folded token
|
|
97
|
+
FOLDED = enum.auto()
|
|
98
|
+
# SINGLE_QUOTE type for SingleQuote token
|
|
99
|
+
SINGLE_QUOTE = enum.auto()
|
|
100
|
+
# DOUBLE_QUOTE type for DoubleQuote token
|
|
101
|
+
DOUBLE_QUOTE = enum.auto()
|
|
102
|
+
# DIRECTIVE type for Directive token
|
|
103
|
+
DIRECTIVE = enum.auto()
|
|
104
|
+
# SPACE type for Space token
|
|
105
|
+
SPACE = enum.auto()
|
|
106
|
+
# NULL type for Null token
|
|
107
|
+
NULL = enum.auto()
|
|
108
|
+
# IMPLICIT_NULL type for implicit Null token.
|
|
109
|
+
# This is used when explicit keywords such as null or ~ are not specified. It is distinguished during encoding and
|
|
110
|
+
# output as an empty string.
|
|
111
|
+
IMPLICIT_NULL = enum.auto()
|
|
112
|
+
# INFINITY type for Infinity token
|
|
113
|
+
INFINITY = enum.auto()
|
|
114
|
+
# NAN type for Nan token
|
|
115
|
+
NAN = enum.auto()
|
|
116
|
+
# INTEGER type for Integer token
|
|
117
|
+
INTEGER = enum.auto()
|
|
118
|
+
# BINARY_INTEGER type for BinaryInteger token
|
|
119
|
+
BINARY_INTEGER = enum.auto()
|
|
120
|
+
# OCTET_INTEGER type for OctetInteger token
|
|
121
|
+
OCTET_INTEGER = enum.auto()
|
|
122
|
+
# HEX_INTEGER type for HexInteger token
|
|
123
|
+
HEX_INTEGER = enum.auto()
|
|
124
|
+
# FLOAT type for Float token
|
|
125
|
+
FLOAT = enum.auto()
|
|
126
|
+
# STRING type for String token
|
|
127
|
+
STRING = enum.auto()
|
|
128
|
+
# BOOL type for Bool token
|
|
129
|
+
BOOL = enum.auto()
|
|
130
|
+
# INVALID type for invalid token
|
|
131
|
+
INVALID = enum.auto()
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class YamlCharType(enum.Enum):
|
|
135
|
+
# INDICATOR type of indicator character
|
|
136
|
+
INDICATOR = enum.auto()
|
|
137
|
+
# WHITE-SPACE type of white space character
|
|
138
|
+
WHITESPACE = enum.auto()
|
|
139
|
+
# MISCELLANEOUS type of miscellaneous character
|
|
140
|
+
MISCELLANEOUS = enum.auto()
|
|
141
|
+
# ESCAPED type of escaped character
|
|
142
|
+
ESCAPED = enum.auto()
|
|
143
|
+
# INVALID type for an invalid token.
|
|
144
|
+
INVALID = enum.auto()
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class YamlIndicator(enum.Enum):
|
|
148
|
+
# NOT not an indicator
|
|
149
|
+
NOT = enum.auto()
|
|
150
|
+
# BLOCK_STRUCTURE indicator for block structure ( '-', '?', ':' )
|
|
151
|
+
BLOCK_STRUCTURE = enum.auto()
|
|
152
|
+
# FLOW_COLLECTION indicator for flow collection ( '[', ']', '{', '}', ',' )
|
|
153
|
+
FLOW_COLLECTION = enum.auto()
|
|
154
|
+
# COMMENT indicator for comment ( '#' )
|
|
155
|
+
COMMENT = enum.auto()
|
|
156
|
+
# NODE_PROPERTY indicator for node property ( '!', '&', '*' )
|
|
157
|
+
NODE_PROPERTY = enum.auto()
|
|
158
|
+
# BLOCK_SCALAR indicator for block scalar ( '|', '>' )
|
|
159
|
+
BLOCK_SCALAR = enum.auto()
|
|
160
|
+
# QUOTED_SCALAR indicator for quoted scalar ( ''', '"' )
|
|
161
|
+
QUOTED_SCALAR = enum.auto()
|
|
162
|
+
# DIRECTIVE indicator for directive ( '%' )
|
|
163
|
+
DIRECTIVE = enum.auto()
|
|
164
|
+
# INVALID_USE_OF_RESERVED indicator for invalid use of reserved keyword ( '@', '`' )
|
|
165
|
+
INVALID_USE_OF_RESERVED = enum.auto()
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
##
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
RESERVED_NULL_KEYWORDS = (
|
|
172
|
+
'null',
|
|
173
|
+
'Null',
|
|
174
|
+
'NULL',
|
|
175
|
+
'~',
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
RESERVED_BOOL_KEYWORDS = (
|
|
180
|
+
'true',
|
|
181
|
+
'True',
|
|
182
|
+
'TRUE',
|
|
183
|
+
'false',
|
|
184
|
+
'False',
|
|
185
|
+
'FALSE',
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
# For compatibility with other YAML 1.1 parsers.
|
|
190
|
+
# Note that we use these solely for encoding the bool value with quotes. go-yaml should not treat these as reserved
|
|
191
|
+
# keywords at parsing time. as go-yaml is supposed to be compliant only with YAML 1.2.
|
|
192
|
+
RESERVED_LEGACY_BOOL_KEYWORDS = (
|
|
193
|
+
'y',
|
|
194
|
+
'Y',
|
|
195
|
+
'yes',
|
|
196
|
+
'Yes',
|
|
197
|
+
'YES',
|
|
198
|
+
'n',
|
|
199
|
+
'N',
|
|
200
|
+
'no',
|
|
201
|
+
'No',
|
|
202
|
+
'NO',
|
|
203
|
+
'on',
|
|
204
|
+
'On',
|
|
205
|
+
'ON',
|
|
206
|
+
'off',
|
|
207
|
+
'Off',
|
|
208
|
+
'OFF',
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
RESERVED_INF_KEYWORDS = (
|
|
213
|
+
'.inf',
|
|
214
|
+
'.Inf',
|
|
215
|
+
'.INF',
|
|
216
|
+
'-.inf',
|
|
217
|
+
'-.Inf',
|
|
218
|
+
'-.INF',
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
RESERVED_NAN_KEYWORDS = (
|
|
223
|
+
'.nan',
|
|
224
|
+
'.NaN',
|
|
225
|
+
'.NAN',
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def reserved_keyword_token(typ: YamlTokenType, value: str, org: str, pos: 'YamlPosition') -> 'YamlToken':
|
|
230
|
+
return YamlToken(
|
|
231
|
+
type=typ,
|
|
232
|
+
char_type=YamlCharType.MISCELLANEOUS,
|
|
233
|
+
indicator=YamlIndicator.NOT,
|
|
234
|
+
value=value,
|
|
235
|
+
origin=org,
|
|
236
|
+
position=pos,
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
RESERVED_KEYWORD_MAP: ta.Mapping[str, ta.Callable[[str, str, 'YamlPosition'], 'YamlToken']] = {
|
|
241
|
+
**{keyword: functools.partial(reserved_keyword_token, YamlTokenType.NULL) for keyword in RESERVED_NULL_KEYWORDS},
|
|
242
|
+
**{keyword: functools.partial(reserved_keyword_token, YamlTokenType.BOOL) for keyword in RESERVED_BOOL_KEYWORDS},
|
|
243
|
+
**{keyword: functools.partial(reserved_keyword_token, YamlTokenType.INFINITY) for keyword in RESERVED_INF_KEYWORDS},
|
|
244
|
+
**{keyword: functools.partial(reserved_keyword_token, YamlTokenType.NAN) for keyword in RESERVED_NAN_KEYWORDS},
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
# RESERVED_ENC_KEYWORD_MAP contains is the keyword map used at encoding time.
|
|
249
|
+
# This is supposed to be a superset of RESERVED_KEYWORD_MAP, and used to quote legacy keywords present in YAML 1.1 or
|
|
250
|
+
# lesser for compatibility reasons, even though this library is supposed to be YAML 1.2-compliant.
|
|
251
|
+
RESERVED_ENC_KEYWORD_MAP: ta.Mapping[str, ta.Callable[[str, str, 'YamlPosition'], 'YamlToken']] = {
|
|
252
|
+
**{keyword: functools.partial(reserved_keyword_token, YamlTokenType.NULL) for keyword in RESERVED_NULL_KEYWORDS},
|
|
253
|
+
**{keyword: functools.partial(reserved_keyword_token, YamlTokenType.BOOL) for keyword in RESERVED_BOOL_KEYWORDS},
|
|
254
|
+
**{keyword: functools.partial(reserved_keyword_token, YamlTokenType.BOOL) for keyword in RESERVED_LEGACY_BOOL_KEYWORDS}, # noqa
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
##
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
YamlReservedTagKeyword = str # ta.TypeAlias # omlish-amalg-typing-no-move
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
class YamlReservedTagKeywords:
|
|
265
|
+
# INTEGER `!!int` tag
|
|
266
|
+
INTEGER = '!!int'
|
|
267
|
+
# FLOAT `!!float` tag
|
|
268
|
+
FLOAT = '!!float'
|
|
269
|
+
# NULL `!!null` tag
|
|
270
|
+
NULL = '!!null'
|
|
271
|
+
# SEQUENCE `!!seq` tag
|
|
272
|
+
SEQUENCE = '!!seq'
|
|
273
|
+
# MAPPING `!!map` tag
|
|
274
|
+
MAPPING = '!!map'
|
|
275
|
+
# STRING `!!str` tag
|
|
276
|
+
STRING = '!!str'
|
|
277
|
+
# BINARY `!!binary` tag
|
|
278
|
+
BINARY = '!!binary'
|
|
279
|
+
# ORDERED_MAP `!!omap` tag
|
|
280
|
+
ORDERED_MAP = '!!omap'
|
|
281
|
+
# SET `!!set` tag
|
|
282
|
+
SET = '!!set'
|
|
283
|
+
# TIMESTAMP `!!timestamp` tag
|
|
284
|
+
TIMESTAMP = '!!timestamp'
|
|
285
|
+
# BOOLEAN `!!bool` tag
|
|
286
|
+
BOOLEAN = '!!bool'
|
|
287
|
+
# MERGE `!!merge` tag
|
|
288
|
+
MERGE = '!!merge'
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
# RESERVED_TAG_KEYWORD_MAP map for reserved tag keywords
|
|
292
|
+
YAML_RESERVED_TAG_KEYWORD_MAP: ta.Mapping[YamlReservedTagKeyword, ta.Callable[[str, str, 'YamlPosition'], 'YamlToken']] = { # noqa
|
|
293
|
+
YamlReservedTagKeywords.INTEGER: lambda value, org, pos: YamlToken(
|
|
294
|
+
type=YamlTokenType.TAG,
|
|
295
|
+
char_type=YamlCharType.INDICATOR,
|
|
296
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
297
|
+
value=value,
|
|
298
|
+
origin=org,
|
|
299
|
+
position=pos,
|
|
300
|
+
),
|
|
301
|
+
YamlReservedTagKeywords.FLOAT: lambda value, org, pos: YamlToken(
|
|
302
|
+
type=YamlTokenType.TAG,
|
|
303
|
+
char_type=YamlCharType.INDICATOR,
|
|
304
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
305
|
+
value=value,
|
|
306
|
+
origin=org,
|
|
307
|
+
position=pos,
|
|
308
|
+
),
|
|
309
|
+
YamlReservedTagKeywords.NULL: lambda value, org, pos: YamlToken(
|
|
310
|
+
type=YamlTokenType.TAG,
|
|
311
|
+
char_type=YamlCharType.INDICATOR,
|
|
312
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
313
|
+
value=value,
|
|
314
|
+
origin=org,
|
|
315
|
+
position=pos,
|
|
316
|
+
),
|
|
317
|
+
YamlReservedTagKeywords.SEQUENCE: lambda value, org, pos: YamlToken(
|
|
318
|
+
type=YamlTokenType.TAG,
|
|
319
|
+
char_type=YamlCharType.INDICATOR,
|
|
320
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
321
|
+
value=value,
|
|
322
|
+
origin=org,
|
|
323
|
+
position=pos,
|
|
324
|
+
),
|
|
325
|
+
YamlReservedTagKeywords.MAPPING: lambda value, org, pos: YamlToken(
|
|
326
|
+
type=YamlTokenType.TAG,
|
|
327
|
+
char_type=YamlCharType.INDICATOR,
|
|
328
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
329
|
+
value=value,
|
|
330
|
+
origin=org,
|
|
331
|
+
position=pos,
|
|
332
|
+
),
|
|
333
|
+
YamlReservedTagKeywords.STRING: lambda value, org, pos: YamlToken(
|
|
334
|
+
type=YamlTokenType.TAG,
|
|
335
|
+
char_type=YamlCharType.INDICATOR,
|
|
336
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
337
|
+
value=value,
|
|
338
|
+
origin=org,
|
|
339
|
+
position=pos,
|
|
340
|
+
),
|
|
341
|
+
YamlReservedTagKeywords.BINARY: lambda value, org, pos: YamlToken(
|
|
342
|
+
type=YamlTokenType.TAG,
|
|
343
|
+
char_type=YamlCharType.INDICATOR,
|
|
344
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
345
|
+
value=value,
|
|
346
|
+
origin=org,
|
|
347
|
+
position=pos,
|
|
348
|
+
),
|
|
349
|
+
YamlReservedTagKeywords.ORDERED_MAP: lambda value, org, pos: YamlToken(
|
|
350
|
+
type=YamlTokenType.TAG,
|
|
351
|
+
char_type=YamlCharType.INDICATOR,
|
|
352
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
353
|
+
value=value,
|
|
354
|
+
origin=org,
|
|
355
|
+
position=pos,
|
|
356
|
+
),
|
|
357
|
+
YamlReservedTagKeywords.SET: lambda value, org, pos: YamlToken(
|
|
358
|
+
type=YamlTokenType.TAG,
|
|
359
|
+
char_type=YamlCharType.INDICATOR,
|
|
360
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
361
|
+
value=value,
|
|
362
|
+
origin=org,
|
|
363
|
+
position=pos,
|
|
364
|
+
),
|
|
365
|
+
YamlReservedTagKeywords.TIMESTAMP: lambda value, org, pos: YamlToken(
|
|
366
|
+
type=YamlTokenType.TAG,
|
|
367
|
+
char_type=YamlCharType.INDICATOR,
|
|
368
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
369
|
+
value=value,
|
|
370
|
+
origin=org,
|
|
371
|
+
position=pos,
|
|
372
|
+
),
|
|
373
|
+
YamlReservedTagKeywords.BOOLEAN: lambda value, org, pos: YamlToken(
|
|
374
|
+
type=YamlTokenType.TAG,
|
|
375
|
+
char_type=YamlCharType.INDICATOR,
|
|
376
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
377
|
+
value=value,
|
|
378
|
+
origin=org,
|
|
379
|
+
position=pos,
|
|
380
|
+
),
|
|
381
|
+
YamlReservedTagKeywords.MERGE: lambda value, org, pos: YamlToken(
|
|
382
|
+
type=YamlTokenType.TAG,
|
|
383
|
+
char_type=YamlCharType.INDICATOR,
|
|
384
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
385
|
+
value=value,
|
|
386
|
+
origin=org,
|
|
387
|
+
position=pos,
|
|
388
|
+
),
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
##
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
class YamlNumberType(enum.Enum):
|
|
396
|
+
DECIMAL = 'decimal'
|
|
397
|
+
BINARY = 'binary'
|
|
398
|
+
OCTET = 'octet'
|
|
399
|
+
HEX = 'hex'
|
|
400
|
+
FLOAT = 'float'
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
@dc.dataclass()
|
|
404
|
+
class YamlNumberValue:
|
|
405
|
+
type: YamlNumberType
|
|
406
|
+
value: ta.Any
|
|
407
|
+
text: str
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
def to_number(value: str) -> ta.Optional[YamlNumberValue]:
|
|
411
|
+
num = _to_number(value)
|
|
412
|
+
if isinstance(num, YamlError):
|
|
413
|
+
return None
|
|
414
|
+
|
|
415
|
+
return num
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def _is_number(value: str) -> bool:
|
|
419
|
+
num = _to_number(value)
|
|
420
|
+
if isinstance(num, YamlError):
|
|
421
|
+
# var numErr *strconv.NumError
|
|
422
|
+
# if errors.As(err, &numErr) && errors.Is(numErr.Err, strconv.ErrRange) {
|
|
423
|
+
# return true
|
|
424
|
+
|
|
425
|
+
return False
|
|
426
|
+
|
|
427
|
+
return num is not None
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def _to_number(value: str) -> YamlErrorOr[ta.Optional[YamlNumberValue]]:
|
|
431
|
+
if not value:
|
|
432
|
+
return None
|
|
433
|
+
|
|
434
|
+
if value.startswith('_'):
|
|
435
|
+
return None
|
|
436
|
+
|
|
437
|
+
dot_count = value.count('.')
|
|
438
|
+
if dot_count > 1:
|
|
439
|
+
return None
|
|
440
|
+
|
|
441
|
+
is_negative = value.startswith('-')
|
|
442
|
+
normalized = value.lstrip('+').lstrip('-').replace('_', '')
|
|
443
|
+
|
|
444
|
+
typ: YamlNumberType
|
|
445
|
+
base = 0
|
|
446
|
+
|
|
447
|
+
if normalized.startswith('0x'):
|
|
448
|
+
normalized = normalized.lstrip('0x')
|
|
449
|
+
base = 16
|
|
450
|
+
typ = YamlNumberType.HEX
|
|
451
|
+
elif normalized.startswith('0o'):
|
|
452
|
+
normalized = normalized.lstrip('0o')
|
|
453
|
+
base = 8
|
|
454
|
+
typ = YamlNumberType.OCTET
|
|
455
|
+
elif normalized.startswith('0b'):
|
|
456
|
+
normalized = normalized.lstrip('0b')
|
|
457
|
+
base = 2
|
|
458
|
+
typ = YamlNumberType.BINARY
|
|
459
|
+
elif normalized.startswith('0') and len(normalized) > 1 and dot_count == 0:
|
|
460
|
+
base = 8
|
|
461
|
+
typ = YamlNumberType.OCTET
|
|
462
|
+
elif dot_count == 1:
|
|
463
|
+
typ = YamlNumberType.FLOAT
|
|
464
|
+
else:
|
|
465
|
+
typ = YamlNumberType.DECIMAL
|
|
466
|
+
base = 10
|
|
467
|
+
|
|
468
|
+
text = normalized
|
|
469
|
+
if is_negative:
|
|
470
|
+
text = '-' + text
|
|
471
|
+
|
|
472
|
+
v: ta.Any
|
|
473
|
+
if typ == YamlNumberType.FLOAT:
|
|
474
|
+
try:
|
|
475
|
+
v = float(text)
|
|
476
|
+
except ValueError as e:
|
|
477
|
+
return yaml_error(e)
|
|
478
|
+
else:
|
|
479
|
+
try:
|
|
480
|
+
v = int(text, base)
|
|
481
|
+
except ValueError as e:
|
|
482
|
+
return yaml_error(e)
|
|
483
|
+
|
|
484
|
+
return YamlNumberValue(
|
|
485
|
+
type=typ,
|
|
486
|
+
value=v,
|
|
487
|
+
text=text,
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
##
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
# This is a subset of the formats permitted by the regular expression defined at http:#yaml.org/type/timestamp.html.
|
|
495
|
+
# Note that time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" from the examples.
|
|
496
|
+
YAML_TIMESTAMP_FORMATS = (
|
|
497
|
+
'%Y-%m-%dT%H:%M:%S.%fZ', # RFC3339Nano
|
|
498
|
+
'%Y-%m-%dt%H:%M:%S.%fZ', # RFC3339Nano with lower-case "t"
|
|
499
|
+
'%Y-%m-%d %H:%M:%S', # DateTime
|
|
500
|
+
'%Y-%m-%d', # DateOnly
|
|
501
|
+
|
|
502
|
+
# Not in examples, but to preserve backward compatibility by quoting time values
|
|
503
|
+
'%H:%M',
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
def _is_timestamp(value: str) -> bool:
|
|
508
|
+
for format_str in YAML_TIMESTAMP_FORMATS:
|
|
509
|
+
try:
|
|
510
|
+
datetime.datetime.strptime(value, format_str) # noqa
|
|
511
|
+
return True
|
|
512
|
+
except ValueError:
|
|
513
|
+
continue
|
|
514
|
+
return False
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
##
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
# is_need_quoted checks whether the value needs quote for passed string or not
|
|
521
|
+
def is_need_quoted(value: str) -> bool:
|
|
522
|
+
if not value:
|
|
523
|
+
return True
|
|
524
|
+
|
|
525
|
+
if value in RESERVED_ENC_KEYWORD_MAP:
|
|
526
|
+
return True
|
|
527
|
+
|
|
528
|
+
if _is_number(value):
|
|
529
|
+
return True
|
|
530
|
+
|
|
531
|
+
if value == '-':
|
|
532
|
+
return True
|
|
533
|
+
|
|
534
|
+
if value[0] in ('*', '&', '[', '{', '}', ']', ',', '!', '|', '>', '%', '\'', '"', '@', ' ', '`'):
|
|
535
|
+
return True
|
|
536
|
+
|
|
537
|
+
if value[-1] in (':', ' '):
|
|
538
|
+
return True
|
|
539
|
+
|
|
540
|
+
if _is_timestamp(value):
|
|
541
|
+
return True
|
|
542
|
+
|
|
543
|
+
for i, c in enumerate(value):
|
|
544
|
+
if c in ('#', '\\'):
|
|
545
|
+
return True
|
|
546
|
+
elif c in (':', '-'):
|
|
547
|
+
if i + 1 < len(value) and value[i + 1] == ' ':
|
|
548
|
+
return True
|
|
549
|
+
|
|
550
|
+
return False
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
# literal_block_header detect literal block scalar header
|
|
554
|
+
def literal_block_header(value: str) -> str:
|
|
555
|
+
lbc = detect_line_break_char(value)
|
|
556
|
+
|
|
557
|
+
if lbc not in value:
|
|
558
|
+
return ''
|
|
559
|
+
elif value.endswith(lbc + lbc):
|
|
560
|
+
return '|+'
|
|
561
|
+
elif value.endswith(lbc):
|
|
562
|
+
return '|'
|
|
563
|
+
else:
|
|
564
|
+
return '|-'
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
##
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
# new create reserved keyword token or number token and other string token.
|
|
571
|
+
def new_yaml_token(value: str, org: str, pos: 'YamlPosition') -> 'YamlToken':
|
|
572
|
+
fn = RESERVED_KEYWORD_MAP.get(value)
|
|
573
|
+
if fn is not None:
|
|
574
|
+
return fn(value, org, pos)
|
|
575
|
+
|
|
576
|
+
if (num := to_number(value)) is not None:
|
|
577
|
+
tk = YamlToken(
|
|
578
|
+
type=YamlTokenType.INTEGER,
|
|
579
|
+
char_type=YamlCharType.MISCELLANEOUS,
|
|
580
|
+
indicator=YamlIndicator.NOT,
|
|
581
|
+
value=value,
|
|
582
|
+
origin=org,
|
|
583
|
+
position=pos,
|
|
584
|
+
)
|
|
585
|
+
if num.type == YamlNumberType.FLOAT:
|
|
586
|
+
tk.type = YamlTokenType.FLOAT
|
|
587
|
+
elif num.type == YamlNumberType.BINARY:
|
|
588
|
+
tk.type = YamlTokenType.BINARY_INTEGER
|
|
589
|
+
elif num.type == YamlNumberType.OCTET:
|
|
590
|
+
tk.type = YamlTokenType.OCTET_INTEGER
|
|
591
|
+
elif num.type == YamlNumberType.HEX:
|
|
592
|
+
tk.type = YamlTokenType.HEX_INTEGER
|
|
593
|
+
return tk
|
|
594
|
+
|
|
595
|
+
return YamlTokenMakers.new_string(value, org, pos)
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
# Position type for position in YAML document
|
|
599
|
+
@dc.dataclass()
|
|
600
|
+
class YamlPosition:
|
|
601
|
+
line: int
|
|
602
|
+
column: int
|
|
603
|
+
offset: int
|
|
604
|
+
indent_num: int
|
|
605
|
+
indent_level: int
|
|
606
|
+
|
|
607
|
+
# String position to text
|
|
608
|
+
def __str__(self) -> str:
|
|
609
|
+
return f'[level:{self.indent_level:d},line:{self.line:d},column:{self.column:d},offset:{self.offset:d}]'
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
# Token type for token
|
|
613
|
+
@dc.dataclass()
|
|
614
|
+
@ta.final
|
|
615
|
+
class YamlToken:
|
|
616
|
+
# Type is a token type.
|
|
617
|
+
type: YamlTokenType
|
|
618
|
+
# CharType is a character type.
|
|
619
|
+
char_type: YamlCharType
|
|
620
|
+
# Indicator is an indicator type.
|
|
621
|
+
indicator: YamlIndicator
|
|
622
|
+
# Value is a string extracted with only meaningful characters, with spaces and such removed.
|
|
623
|
+
value: str
|
|
624
|
+
# Origin is a string that stores the original text as-is.
|
|
625
|
+
origin: str
|
|
626
|
+
# Error keeps error message for InvalidToken.
|
|
627
|
+
error: ta.Optional[YamlError] = None
|
|
628
|
+
# Position is a token position.
|
|
629
|
+
position: YamlPosition = dc.field(default_factory=dataclass_field_required('position'))
|
|
630
|
+
# Next is a next token reference.
|
|
631
|
+
next: ta.Optional['YamlToken'] = dc.field(default=None, repr=False)
|
|
632
|
+
# Prev is a previous token reference.
|
|
633
|
+
prev: ta.Optional['YamlToken'] = dc.field(default=None, repr=False)
|
|
634
|
+
|
|
635
|
+
# previous_type previous token type
|
|
636
|
+
def previous_type(self) -> YamlTokenType:
|
|
637
|
+
if self.prev is not None:
|
|
638
|
+
return self.prev.type
|
|
639
|
+
|
|
640
|
+
return YamlTokenType.UNKNOWN
|
|
641
|
+
|
|
642
|
+
# next_type next token type
|
|
643
|
+
def next_type(self) -> YamlTokenType:
|
|
644
|
+
if self.next is not None:
|
|
645
|
+
return self.next.type
|
|
646
|
+
|
|
647
|
+
return YamlTokenType.UNKNOWN
|
|
648
|
+
|
|
649
|
+
# add_column append column number to current position of column
|
|
650
|
+
@classmethod
|
|
651
|
+
def add_column(cls, t: ta.Optional['YamlToken'], col: int) -> None:
|
|
652
|
+
if t is None:
|
|
653
|
+
return
|
|
654
|
+
|
|
655
|
+
t.position.column += col
|
|
656
|
+
|
|
657
|
+
# clone copy token ( preserve Prev/Next reference )
|
|
658
|
+
@classmethod
|
|
659
|
+
def clone(cls, t: ta.Optional['YamlToken']) -> ta.Optional['YamlToken']:
|
|
660
|
+
if t is None:
|
|
661
|
+
return None
|
|
662
|
+
|
|
663
|
+
copied = copy.copy(t)
|
|
664
|
+
if t.position is not None:
|
|
665
|
+
pos = copy.copy(t.position)
|
|
666
|
+
copied.position = pos
|
|
667
|
+
|
|
668
|
+
return copied
|
|
669
|
+
|
|
670
|
+
|
|
671
|
+
##
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
# Tokens type of token collection
|
|
675
|
+
class YamlTokens(ta.List[YamlToken]):
|
|
676
|
+
def invalid_token(self) -> ta.Optional[YamlToken]:
|
|
677
|
+
for tt in self:
|
|
678
|
+
if tt.type == YamlTokenType.INVALID:
|
|
679
|
+
return tt
|
|
680
|
+
return None
|
|
681
|
+
|
|
682
|
+
def _add(self, tk: YamlToken) -> None:
|
|
683
|
+
if not self:
|
|
684
|
+
self.append(tk)
|
|
685
|
+
else:
|
|
686
|
+
last = self[-1]
|
|
687
|
+
last.next = tk
|
|
688
|
+
tk.prev = last
|
|
689
|
+
self.append(tk)
|
|
690
|
+
|
|
691
|
+
# add append new some tokens
|
|
692
|
+
def add(self, *tks: YamlToken) -> None:
|
|
693
|
+
for tk in tks:
|
|
694
|
+
self._add(tk)
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
##
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
class YamlTokenMakers: # noqa
|
|
701
|
+
def __new__(cls, *args, **kwargs): # noqa
|
|
702
|
+
raise TypeError
|
|
703
|
+
|
|
704
|
+
# new_string create token for String
|
|
705
|
+
@staticmethod
|
|
706
|
+
def new_string(value: str, org: str, pos: YamlPosition) -> YamlToken:
|
|
707
|
+
return YamlToken(
|
|
708
|
+
type=YamlTokenType.STRING,
|
|
709
|
+
char_type=YamlCharType.MISCELLANEOUS,
|
|
710
|
+
indicator=YamlIndicator.NOT,
|
|
711
|
+
value=value,
|
|
712
|
+
origin=org,
|
|
713
|
+
position=pos,
|
|
714
|
+
)
|
|
715
|
+
|
|
716
|
+
# new_sequence_entry create token for SequenceEntry
|
|
717
|
+
@staticmethod
|
|
718
|
+
def new_sequence_entry(org: str, pos: YamlPosition) -> YamlToken:
|
|
719
|
+
return YamlToken(
|
|
720
|
+
type=YamlTokenType.SEQUENCE_ENTRY,
|
|
721
|
+
char_type=YamlCharType.INDICATOR,
|
|
722
|
+
indicator=YamlIndicator.BLOCK_STRUCTURE,
|
|
723
|
+
value=YamlChars.SEQUENCE_ENTRY,
|
|
724
|
+
origin=org,
|
|
725
|
+
position=pos,
|
|
726
|
+
)
|
|
727
|
+
|
|
728
|
+
# new_mapping_key create token for MappingKey
|
|
729
|
+
@staticmethod
|
|
730
|
+
def new_mapping_key(pos: YamlPosition) -> YamlToken:
|
|
731
|
+
return YamlToken(
|
|
732
|
+
type=YamlTokenType.MAPPING_KEY,
|
|
733
|
+
char_type=YamlCharType.INDICATOR,
|
|
734
|
+
indicator=YamlIndicator.BLOCK_STRUCTURE,
|
|
735
|
+
value=YamlChars.MAPPING_KEY,
|
|
736
|
+
origin=YamlChars.MAPPING_KEY,
|
|
737
|
+
position=pos,
|
|
738
|
+
)
|
|
739
|
+
|
|
740
|
+
# new_mapping_value create token for MappingValue
|
|
741
|
+
@staticmethod
|
|
742
|
+
def new_mapping_value(pos: YamlPosition) -> YamlToken:
|
|
743
|
+
return YamlToken(
|
|
744
|
+
type=YamlTokenType.MAPPING_VALUE,
|
|
745
|
+
char_type=YamlCharType.INDICATOR,
|
|
746
|
+
indicator=YamlIndicator.BLOCK_STRUCTURE,
|
|
747
|
+
value=YamlChars.MAPPING_VALUE,
|
|
748
|
+
origin=YamlChars.MAPPING_VALUE,
|
|
749
|
+
position=pos,
|
|
750
|
+
)
|
|
751
|
+
|
|
752
|
+
# new_collect_entry create token for CollectEntry
|
|
753
|
+
@staticmethod
|
|
754
|
+
def new_collect_entry(org: str, pos: YamlPosition) -> YamlToken:
|
|
755
|
+
return YamlToken(
|
|
756
|
+
type=YamlTokenType.COLLECT_ENTRY,
|
|
757
|
+
char_type=YamlCharType.INDICATOR,
|
|
758
|
+
indicator=YamlIndicator.FLOW_COLLECTION,
|
|
759
|
+
value=YamlChars.COLLECT_ENTRY,
|
|
760
|
+
origin=org,
|
|
761
|
+
position=pos,
|
|
762
|
+
)
|
|
763
|
+
|
|
764
|
+
# new_sequence_start create token for SequenceStart
|
|
765
|
+
@staticmethod
|
|
766
|
+
def new_sequence_start(org: str, pos: YamlPosition) -> YamlToken:
|
|
767
|
+
return YamlToken(
|
|
768
|
+
type=YamlTokenType.SEQUENCE_START,
|
|
769
|
+
char_type=YamlCharType.INDICATOR,
|
|
770
|
+
indicator=YamlIndicator.FLOW_COLLECTION,
|
|
771
|
+
value=YamlChars.SEQUENCE_START,
|
|
772
|
+
origin=org,
|
|
773
|
+
position=pos,
|
|
774
|
+
)
|
|
775
|
+
|
|
776
|
+
# new_sequence_end create token for SequenceEnd
|
|
777
|
+
@staticmethod
|
|
778
|
+
def new_sequence_end(org: str, pos: YamlPosition) -> YamlToken:
|
|
779
|
+
return YamlToken(
|
|
780
|
+
type=YamlTokenType.SEQUENCE_END,
|
|
781
|
+
char_type=YamlCharType.INDICATOR,
|
|
782
|
+
indicator=YamlIndicator.FLOW_COLLECTION,
|
|
783
|
+
value=YamlChars.SEQUENCE_END,
|
|
784
|
+
origin=org,
|
|
785
|
+
position=pos,
|
|
786
|
+
)
|
|
787
|
+
|
|
788
|
+
# new_mapping_start create token for MappingStart
|
|
789
|
+
@staticmethod
|
|
790
|
+
def new_mapping_start(org: str, pos: YamlPosition) -> YamlToken:
|
|
791
|
+
return YamlToken(
|
|
792
|
+
type=YamlTokenType.MAPPING_START,
|
|
793
|
+
char_type=YamlCharType.INDICATOR,
|
|
794
|
+
indicator=YamlIndicator.FLOW_COLLECTION,
|
|
795
|
+
value=YamlChars.MAPPING_START,
|
|
796
|
+
origin=org,
|
|
797
|
+
position=pos,
|
|
798
|
+
)
|
|
799
|
+
|
|
800
|
+
# new_mapping_end create token for MappingEnd
|
|
801
|
+
@staticmethod
|
|
802
|
+
def new_mapping_end(org: str, pos: YamlPosition) -> YamlToken:
|
|
803
|
+
return YamlToken(
|
|
804
|
+
type=YamlTokenType.MAPPING_END,
|
|
805
|
+
char_type=YamlCharType.INDICATOR,
|
|
806
|
+
indicator=YamlIndicator.FLOW_COLLECTION,
|
|
807
|
+
value=YamlChars.MAPPING_END,
|
|
808
|
+
origin=org,
|
|
809
|
+
position=pos,
|
|
810
|
+
)
|
|
811
|
+
|
|
812
|
+
# new_comment create token for Comment
|
|
813
|
+
@staticmethod
|
|
814
|
+
def new_comment(value: str, org: str, pos: YamlPosition) -> YamlToken:
|
|
815
|
+
return YamlToken(
|
|
816
|
+
type=YamlTokenType.COMMENT,
|
|
817
|
+
char_type=YamlCharType.INDICATOR,
|
|
818
|
+
indicator=YamlIndicator.COMMENT,
|
|
819
|
+
value=value,
|
|
820
|
+
origin=org,
|
|
821
|
+
position=pos,
|
|
822
|
+
)
|
|
823
|
+
|
|
824
|
+
# new_anchor create token for Anchor
|
|
825
|
+
@staticmethod
|
|
826
|
+
def new_anchor(org: str, pos: YamlPosition) -> YamlToken:
|
|
827
|
+
return YamlToken(
|
|
828
|
+
type=YamlTokenType.ANCHOR,
|
|
829
|
+
char_type=YamlCharType.INDICATOR,
|
|
830
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
831
|
+
value=YamlChars.ANCHOR,
|
|
832
|
+
origin=org,
|
|
833
|
+
position=pos,
|
|
834
|
+
)
|
|
835
|
+
|
|
836
|
+
# new_alias create token for Alias
|
|
837
|
+
@staticmethod
|
|
838
|
+
def new_alias(org: str, pos: YamlPosition) -> YamlToken:
|
|
839
|
+
return YamlToken(
|
|
840
|
+
type=YamlTokenType.ALIAS,
|
|
841
|
+
char_type=YamlCharType.INDICATOR,
|
|
842
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
843
|
+
value=YamlChars.ALIAS,
|
|
844
|
+
origin=org,
|
|
845
|
+
position=pos,
|
|
846
|
+
)
|
|
847
|
+
|
|
848
|
+
# new_tag create token for Tag
|
|
849
|
+
@staticmethod
|
|
850
|
+
def new_tag(value: str, org: str, pos: YamlPosition) -> YamlToken:
|
|
851
|
+
fn = YAML_RESERVED_TAG_KEYWORD_MAP.get(value)
|
|
852
|
+
if fn is not None:
|
|
853
|
+
return fn(value, org, pos)
|
|
854
|
+
|
|
855
|
+
return YamlToken(
|
|
856
|
+
type=YamlTokenType.TAG,
|
|
857
|
+
char_type=YamlCharType.INDICATOR,
|
|
858
|
+
indicator=YamlIndicator.NODE_PROPERTY,
|
|
859
|
+
value=value,
|
|
860
|
+
origin=org,
|
|
861
|
+
position=pos,
|
|
862
|
+
)
|
|
863
|
+
|
|
864
|
+
# new_literal create token for Literal
|
|
865
|
+
@staticmethod
|
|
866
|
+
def new_literal(value: str, org: str, pos: YamlPosition) -> YamlToken:
|
|
867
|
+
return YamlToken(
|
|
868
|
+
type=YamlTokenType.LITERAL,
|
|
869
|
+
char_type=YamlCharType.INDICATOR,
|
|
870
|
+
indicator=YamlIndicator.BLOCK_SCALAR,
|
|
871
|
+
value=value,
|
|
872
|
+
origin=org,
|
|
873
|
+
position=pos,
|
|
874
|
+
)
|
|
875
|
+
|
|
876
|
+
# new_folded create token for Folded
|
|
877
|
+
@staticmethod
|
|
878
|
+
def new_folded(value: str, org: str, pos: YamlPosition) -> YamlToken:
|
|
879
|
+
return YamlToken(
|
|
880
|
+
type=YamlTokenType.FOLDED,
|
|
881
|
+
char_type=YamlCharType.INDICATOR,
|
|
882
|
+
indicator=YamlIndicator.BLOCK_SCALAR,
|
|
883
|
+
value=value,
|
|
884
|
+
origin=org,
|
|
885
|
+
position=pos,
|
|
886
|
+
)
|
|
887
|
+
|
|
888
|
+
# new_single_quote create token for SingleQuote
|
|
889
|
+
@staticmethod
|
|
890
|
+
def new_single_quote(value: str, org: str, pos: YamlPosition) -> YamlToken:
|
|
891
|
+
return YamlToken(
|
|
892
|
+
type=YamlTokenType.SINGLE_QUOTE,
|
|
893
|
+
char_type=YamlCharType.INDICATOR,
|
|
894
|
+
indicator=YamlIndicator.QUOTED_SCALAR,
|
|
895
|
+
value=value,
|
|
896
|
+
origin=org,
|
|
897
|
+
position=pos,
|
|
898
|
+
)
|
|
899
|
+
|
|
900
|
+
# new_double_quote create token for DoubleQuote
|
|
901
|
+
@staticmethod
|
|
902
|
+
def new_double_quote(value: str, org: str, pos: YamlPosition) -> YamlToken:
|
|
903
|
+
return YamlToken(
|
|
904
|
+
type=YamlTokenType.DOUBLE_QUOTE,
|
|
905
|
+
char_type=YamlCharType.INDICATOR,
|
|
906
|
+
indicator=YamlIndicator.QUOTED_SCALAR,
|
|
907
|
+
value=value,
|
|
908
|
+
origin=org,
|
|
909
|
+
position=pos,
|
|
910
|
+
)
|
|
911
|
+
|
|
912
|
+
# new_directive create token for Directive
|
|
913
|
+
@staticmethod
|
|
914
|
+
def new_directive(org: str, pos: YamlPosition) -> YamlToken:
|
|
915
|
+
return YamlToken(
|
|
916
|
+
type=YamlTokenType.DIRECTIVE,
|
|
917
|
+
char_type=YamlCharType.INDICATOR,
|
|
918
|
+
indicator=YamlIndicator.DIRECTIVE,
|
|
919
|
+
value=YamlChars.DIRECTIVE,
|
|
920
|
+
origin=org,
|
|
921
|
+
position=pos,
|
|
922
|
+
)
|
|
923
|
+
|
|
924
|
+
# new_space create token for Space
|
|
925
|
+
@staticmethod
|
|
926
|
+
def new_space(pos: YamlPosition) -> YamlToken:
|
|
927
|
+
return YamlToken(
|
|
928
|
+
type=YamlTokenType.SPACE,
|
|
929
|
+
char_type=YamlCharType.WHITESPACE,
|
|
930
|
+
indicator=YamlIndicator.NOT,
|
|
931
|
+
value=YamlChars.SPACE,
|
|
932
|
+
origin=YamlChars.SPACE,
|
|
933
|
+
position=pos,
|
|
934
|
+
)
|
|
935
|
+
|
|
936
|
+
# new_merge_key create token for MergeKey
|
|
937
|
+
@staticmethod
|
|
938
|
+
def new_merge_key(org: str, pos: YamlPosition) -> YamlToken:
|
|
939
|
+
return YamlToken(
|
|
940
|
+
type=YamlTokenType.MERGE_KEY,
|
|
941
|
+
char_type=YamlCharType.MISCELLANEOUS,
|
|
942
|
+
indicator=YamlIndicator.NOT,
|
|
943
|
+
value='<<',
|
|
944
|
+
origin=org,
|
|
945
|
+
position=pos,
|
|
946
|
+
)
|
|
947
|
+
|
|
948
|
+
# new_document_header create token for DocumentHeader
|
|
949
|
+
@staticmethod
|
|
950
|
+
def new_document_header(org: str, pos: YamlPosition) -> YamlToken:
|
|
951
|
+
return YamlToken(
|
|
952
|
+
type=YamlTokenType.DOCUMENT_HEADER,
|
|
953
|
+
char_type=YamlCharType.MISCELLANEOUS,
|
|
954
|
+
indicator=YamlIndicator.NOT,
|
|
955
|
+
value='---',
|
|
956
|
+
origin=org,
|
|
957
|
+
position=pos,
|
|
958
|
+
)
|
|
959
|
+
|
|
960
|
+
# new_document_end create token for DocumentEnd
|
|
961
|
+
@staticmethod
|
|
962
|
+
def new_document_end(org: str, pos: YamlPosition) -> YamlToken:
|
|
963
|
+
return YamlToken(
|
|
964
|
+
type=YamlTokenType.DOCUMENT_END,
|
|
965
|
+
char_type=YamlCharType.MISCELLANEOUS,
|
|
966
|
+
indicator=YamlIndicator.NOT,
|
|
967
|
+
value='...',
|
|
968
|
+
origin=org,
|
|
969
|
+
position=pos,
|
|
970
|
+
)
|
|
971
|
+
|
|
972
|
+
@staticmethod
|
|
973
|
+
def new_invalid(err: YamlError, org: str, pos: YamlPosition) -> YamlToken:
|
|
974
|
+
return YamlToken(
|
|
975
|
+
type=YamlTokenType.INVALID,
|
|
976
|
+
char_type=YamlCharType.INVALID,
|
|
977
|
+
indicator=YamlIndicator.NOT,
|
|
978
|
+
value=org,
|
|
979
|
+
origin=org,
|
|
980
|
+
error=err,
|
|
981
|
+
position=pos,
|
|
982
|
+
)
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
##
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
# detect_line_break_char detect line break character in only one inside scalar content scope.
|
|
989
|
+
def detect_line_break_char(src: str) -> str:
|
|
990
|
+
nc = src.count('\n')
|
|
991
|
+
rc = src.count('\r')
|
|
992
|
+
rnc = src.count('\r\n')
|
|
993
|
+
if nc == rnc and rc == rnc:
|
|
994
|
+
return '\r\n'
|
|
995
|
+
elif rc > nc:
|
|
996
|
+
return '\r'
|
|
997
|
+
else:
|
|
998
|
+
return '\n'
|