1a5f9918aSopenharmony_ci
2a5f9918aSopenharmony_ciimport yaml, yaml.composer, yaml.constructor, yaml.resolver
3a5f9918aSopenharmony_ci
4a5f9918aSopenharmony_ciclass CanonicalError(yaml.YAMLError):
5a5f9918aSopenharmony_ci    pass
6a5f9918aSopenharmony_ci
7a5f9918aSopenharmony_ciclass CanonicalScanner:
8a5f9918aSopenharmony_ci
9a5f9918aSopenharmony_ci    def __init__(self, data):
10a5f9918aSopenharmony_ci        if isinstance(data, bytes):
11a5f9918aSopenharmony_ci            try:
12a5f9918aSopenharmony_ci                data = data.decode('utf-8')
13a5f9918aSopenharmony_ci            except UnicodeDecodeError:
14a5f9918aSopenharmony_ci                raise CanonicalError("utf-8 stream is expected")
15a5f9918aSopenharmony_ci        self.data = data+'\0'
16a5f9918aSopenharmony_ci        self.index = 0
17a5f9918aSopenharmony_ci        self.tokens = []
18a5f9918aSopenharmony_ci        self.scanned = False
19a5f9918aSopenharmony_ci
20a5f9918aSopenharmony_ci    def check_token(self, *choices):
21a5f9918aSopenharmony_ci        if not self.scanned:
22a5f9918aSopenharmony_ci            self.scan()
23a5f9918aSopenharmony_ci        if self.tokens:
24a5f9918aSopenharmony_ci            if not choices:
25a5f9918aSopenharmony_ci                return True
26a5f9918aSopenharmony_ci            for choice in choices:
27a5f9918aSopenharmony_ci                if isinstance(self.tokens[0], choice):
28a5f9918aSopenharmony_ci                    return True
29a5f9918aSopenharmony_ci        return False
30a5f9918aSopenharmony_ci
31a5f9918aSopenharmony_ci    def peek_token(self):
32a5f9918aSopenharmony_ci        if not self.scanned:
33a5f9918aSopenharmony_ci            self.scan()
34a5f9918aSopenharmony_ci        if self.tokens:
35a5f9918aSopenharmony_ci            return self.tokens[0]
36a5f9918aSopenharmony_ci
37a5f9918aSopenharmony_ci    def get_token(self, choice=None):
38a5f9918aSopenharmony_ci        if not self.scanned:
39a5f9918aSopenharmony_ci            self.scan()
40a5f9918aSopenharmony_ci        token = self.tokens.pop(0)
41a5f9918aSopenharmony_ci        if choice and not isinstance(token, choice):
42a5f9918aSopenharmony_ci            raise CanonicalError("unexpected token "+repr(token))
43a5f9918aSopenharmony_ci        return token
44a5f9918aSopenharmony_ci
45a5f9918aSopenharmony_ci    def get_token_value(self):
46a5f9918aSopenharmony_ci        token = self.get_token()
47a5f9918aSopenharmony_ci        return token.value
48a5f9918aSopenharmony_ci
49a5f9918aSopenharmony_ci    def scan(self):
50a5f9918aSopenharmony_ci        self.tokens.append(yaml.StreamStartToken(None, None))
51a5f9918aSopenharmony_ci        while True:
52a5f9918aSopenharmony_ci            self.find_token()
53a5f9918aSopenharmony_ci            ch = self.data[self.index]
54a5f9918aSopenharmony_ci            if ch == '\0':
55a5f9918aSopenharmony_ci                self.tokens.append(yaml.StreamEndToken(None, None))
56a5f9918aSopenharmony_ci                break
57a5f9918aSopenharmony_ci            elif ch == '%':
58a5f9918aSopenharmony_ci                self.tokens.append(self.scan_directive())
59a5f9918aSopenharmony_ci            elif ch == '-' and self.data[self.index:self.index+3] == '---':
60a5f9918aSopenharmony_ci                self.index += 3
61a5f9918aSopenharmony_ci                self.tokens.append(yaml.DocumentStartToken(None, None))
62a5f9918aSopenharmony_ci            elif ch == '[':
63a5f9918aSopenharmony_ci                self.index += 1
64a5f9918aSopenharmony_ci                self.tokens.append(yaml.FlowSequenceStartToken(None, None))
65a5f9918aSopenharmony_ci            elif ch == '{':
66a5f9918aSopenharmony_ci                self.index += 1
67a5f9918aSopenharmony_ci                self.tokens.append(yaml.FlowMappingStartToken(None, None))
68a5f9918aSopenharmony_ci            elif ch == ']':
69a5f9918aSopenharmony_ci                self.index += 1
70a5f9918aSopenharmony_ci                self.tokens.append(yaml.FlowSequenceEndToken(None, None))
71a5f9918aSopenharmony_ci            elif ch == '}':
72a5f9918aSopenharmony_ci                self.index += 1
73a5f9918aSopenharmony_ci                self.tokens.append(yaml.FlowMappingEndToken(None, None))
74a5f9918aSopenharmony_ci            elif ch == '?':
75a5f9918aSopenharmony_ci                self.index += 1
76a5f9918aSopenharmony_ci                self.tokens.append(yaml.KeyToken(None, None))
77a5f9918aSopenharmony_ci            elif ch == ':':
78a5f9918aSopenharmony_ci                self.index += 1
79a5f9918aSopenharmony_ci                self.tokens.append(yaml.ValueToken(None, None))
80a5f9918aSopenharmony_ci            elif ch == ',':
81a5f9918aSopenharmony_ci                self.index += 1
82a5f9918aSopenharmony_ci                self.tokens.append(yaml.FlowEntryToken(None, None))
83a5f9918aSopenharmony_ci            elif ch == '*' or ch == '&':
84a5f9918aSopenharmony_ci                self.tokens.append(self.scan_alias())
85a5f9918aSopenharmony_ci            elif ch == '!':
86a5f9918aSopenharmony_ci                self.tokens.append(self.scan_tag())
87a5f9918aSopenharmony_ci            elif ch == '"':
88a5f9918aSopenharmony_ci                self.tokens.append(self.scan_scalar())
89a5f9918aSopenharmony_ci            else:
90a5f9918aSopenharmony_ci                raise CanonicalError("invalid token")
91a5f9918aSopenharmony_ci        self.scanned = True
92a5f9918aSopenharmony_ci
93a5f9918aSopenharmony_ci    DIRECTIVE = '%YAML 1.1'
94a5f9918aSopenharmony_ci
95a5f9918aSopenharmony_ci    def scan_directive(self):
96a5f9918aSopenharmony_ci        if self.data[self.index:self.index+len(self.DIRECTIVE)] == self.DIRECTIVE and \
97a5f9918aSopenharmony_ci                self.data[self.index+len(self.DIRECTIVE)] in ' \n\0':
98a5f9918aSopenharmony_ci            self.index += len(self.DIRECTIVE)
99a5f9918aSopenharmony_ci            return yaml.DirectiveToken('YAML', (1, 1), None, None)
100a5f9918aSopenharmony_ci        else:
101a5f9918aSopenharmony_ci            raise CanonicalError("invalid directive")
102a5f9918aSopenharmony_ci
103a5f9918aSopenharmony_ci    def scan_alias(self):
104a5f9918aSopenharmony_ci        if self.data[self.index] == '*':
105a5f9918aSopenharmony_ci            TokenClass = yaml.AliasToken
106a5f9918aSopenharmony_ci        else:
107a5f9918aSopenharmony_ci            TokenClass = yaml.AnchorToken
108a5f9918aSopenharmony_ci        self.index += 1
109a5f9918aSopenharmony_ci        start = self.index
110a5f9918aSopenharmony_ci        while self.data[self.index] not in ', \n\0':
111a5f9918aSopenharmony_ci            self.index += 1
112a5f9918aSopenharmony_ci        value = self.data[start:self.index]
113a5f9918aSopenharmony_ci        return TokenClass(value, None, None)
114a5f9918aSopenharmony_ci
115a5f9918aSopenharmony_ci    def scan_tag(self):
116a5f9918aSopenharmony_ci        self.index += 1
117a5f9918aSopenharmony_ci        start = self.index
118a5f9918aSopenharmony_ci        while self.data[self.index] not in ' \n\0':
119a5f9918aSopenharmony_ci            self.index += 1
120a5f9918aSopenharmony_ci        value = self.data[start:self.index]
121a5f9918aSopenharmony_ci        if not value:
122a5f9918aSopenharmony_ci            value = '!'
123a5f9918aSopenharmony_ci        elif value[0] == '!':
124a5f9918aSopenharmony_ci            value = 'tag:yaml.org,2002:'+value[1:]
125a5f9918aSopenharmony_ci        elif value[0] == '<' and value[-1] == '>':
126a5f9918aSopenharmony_ci            value = value[1:-1]
127a5f9918aSopenharmony_ci        else:
128a5f9918aSopenharmony_ci            value = '!'+value
129a5f9918aSopenharmony_ci        return yaml.TagToken(value, None, None)
130a5f9918aSopenharmony_ci
131a5f9918aSopenharmony_ci    QUOTE_CODES = {
132a5f9918aSopenharmony_ci        'x': 2,
133a5f9918aSopenharmony_ci        'u': 4,
134a5f9918aSopenharmony_ci        'U': 8,
135a5f9918aSopenharmony_ci    }
136a5f9918aSopenharmony_ci
137a5f9918aSopenharmony_ci    QUOTE_REPLACES = {
138a5f9918aSopenharmony_ci        '\\': '\\',
139a5f9918aSopenharmony_ci        '\"': '\"',
140a5f9918aSopenharmony_ci        ' ': ' ',
141a5f9918aSopenharmony_ci        'a': '\x07',
142a5f9918aSopenharmony_ci        'b': '\x08',
143a5f9918aSopenharmony_ci        'e': '\x1B',
144a5f9918aSopenharmony_ci        'f': '\x0C',
145a5f9918aSopenharmony_ci        'n': '\x0A',
146a5f9918aSopenharmony_ci        'r': '\x0D',
147a5f9918aSopenharmony_ci        't': '\x09',
148a5f9918aSopenharmony_ci        'v': '\x0B',
149a5f9918aSopenharmony_ci        'N': '\u0085',
150a5f9918aSopenharmony_ci        'L': '\u2028',
151a5f9918aSopenharmony_ci        'P': '\u2029',
152a5f9918aSopenharmony_ci        '_': '_',
153a5f9918aSopenharmony_ci        '0': '\x00',
154a5f9918aSopenharmony_ci    }
155a5f9918aSopenharmony_ci
156a5f9918aSopenharmony_ci    def scan_scalar(self):
157a5f9918aSopenharmony_ci        self.index += 1
158a5f9918aSopenharmony_ci        chunks = []
159a5f9918aSopenharmony_ci        start = self.index
160a5f9918aSopenharmony_ci        ignore_spaces = False
161a5f9918aSopenharmony_ci        while self.data[self.index] != '"':
162a5f9918aSopenharmony_ci            if self.data[self.index] == '\\':
163a5f9918aSopenharmony_ci                ignore_spaces = False
164a5f9918aSopenharmony_ci                chunks.append(self.data[start:self.index])
165a5f9918aSopenharmony_ci                self.index += 1
166a5f9918aSopenharmony_ci                ch = self.data[self.index]
167a5f9918aSopenharmony_ci                self.index += 1
168a5f9918aSopenharmony_ci                if ch == '\n':
169a5f9918aSopenharmony_ci                    ignore_spaces = True
170a5f9918aSopenharmony_ci                elif ch in self.QUOTE_CODES:
171a5f9918aSopenharmony_ci                    length = self.QUOTE_CODES[ch]
172a5f9918aSopenharmony_ci                    code = int(self.data[self.index:self.index+length], 16)
173a5f9918aSopenharmony_ci                    chunks.append(chr(code))
174a5f9918aSopenharmony_ci                    self.index += length
175a5f9918aSopenharmony_ci                else:
176a5f9918aSopenharmony_ci                    if ch not in self.QUOTE_REPLACES:
177a5f9918aSopenharmony_ci                        raise CanonicalError("invalid escape code")
178a5f9918aSopenharmony_ci                    chunks.append(self.QUOTE_REPLACES[ch])
179a5f9918aSopenharmony_ci                start = self.index
180a5f9918aSopenharmony_ci            elif self.data[self.index] == '\n':
181a5f9918aSopenharmony_ci                chunks.append(self.data[start:self.index])
182a5f9918aSopenharmony_ci                chunks.append(' ')
183a5f9918aSopenharmony_ci                self.index += 1
184a5f9918aSopenharmony_ci                start = self.index
185a5f9918aSopenharmony_ci                ignore_spaces = True
186a5f9918aSopenharmony_ci            elif ignore_spaces and self.data[self.index] == ' ':
187a5f9918aSopenharmony_ci                self.index += 1
188a5f9918aSopenharmony_ci                start = self.index
189a5f9918aSopenharmony_ci            else:
190a5f9918aSopenharmony_ci                ignore_spaces = False
191a5f9918aSopenharmony_ci                self.index += 1
192a5f9918aSopenharmony_ci        chunks.append(self.data[start:self.index])
193a5f9918aSopenharmony_ci        self.index += 1
194a5f9918aSopenharmony_ci        return yaml.ScalarToken(''.join(chunks), False, None, None)
195a5f9918aSopenharmony_ci
196a5f9918aSopenharmony_ci    def find_token(self):
197a5f9918aSopenharmony_ci        found = False
198a5f9918aSopenharmony_ci        while not found:
199a5f9918aSopenharmony_ci            while self.data[self.index] in ' \t':
200a5f9918aSopenharmony_ci                self.index += 1
201a5f9918aSopenharmony_ci            if self.data[self.index] == '#':
202a5f9918aSopenharmony_ci                while self.data[self.index] != '\n':
203a5f9918aSopenharmony_ci                    self.index += 1
204a5f9918aSopenharmony_ci            if self.data[self.index] == '\n':
205a5f9918aSopenharmony_ci                self.index += 1
206a5f9918aSopenharmony_ci            else:
207a5f9918aSopenharmony_ci                found = True
208a5f9918aSopenharmony_ci
209a5f9918aSopenharmony_ciclass CanonicalParser:
210a5f9918aSopenharmony_ci
211a5f9918aSopenharmony_ci    def __init__(self):
212a5f9918aSopenharmony_ci        self.events = []
213a5f9918aSopenharmony_ci        self.parsed = False
214a5f9918aSopenharmony_ci
215a5f9918aSopenharmony_ci    def dispose(self):
216a5f9918aSopenharmony_ci        pass
217a5f9918aSopenharmony_ci
218a5f9918aSopenharmony_ci    # stream: STREAM-START document* STREAM-END
219a5f9918aSopenharmony_ci    def parse_stream(self):
220a5f9918aSopenharmony_ci        self.get_token(yaml.StreamStartToken)
221a5f9918aSopenharmony_ci        self.events.append(yaml.StreamStartEvent(None, None))
222a5f9918aSopenharmony_ci        while not self.check_token(yaml.StreamEndToken):
223a5f9918aSopenharmony_ci            if self.check_token(yaml.DirectiveToken, yaml.DocumentStartToken):
224a5f9918aSopenharmony_ci                self.parse_document()
225a5f9918aSopenharmony_ci            else:
226a5f9918aSopenharmony_ci                raise CanonicalError("document is expected, got "+repr(self.tokens[0]))
227a5f9918aSopenharmony_ci        self.get_token(yaml.StreamEndToken)
228a5f9918aSopenharmony_ci        self.events.append(yaml.StreamEndEvent(None, None))
229a5f9918aSopenharmony_ci
230a5f9918aSopenharmony_ci    # document: DIRECTIVE? DOCUMENT-START node
231a5f9918aSopenharmony_ci    def parse_document(self):
232a5f9918aSopenharmony_ci        node = None
233a5f9918aSopenharmony_ci        if self.check_token(yaml.DirectiveToken):
234a5f9918aSopenharmony_ci            self.get_token(yaml.DirectiveToken)
235a5f9918aSopenharmony_ci        self.get_token(yaml.DocumentStartToken)
236a5f9918aSopenharmony_ci        self.events.append(yaml.DocumentStartEvent(None, None))
237a5f9918aSopenharmony_ci        self.parse_node()
238a5f9918aSopenharmony_ci        self.events.append(yaml.DocumentEndEvent(None, None))
239a5f9918aSopenharmony_ci
240a5f9918aSopenharmony_ci    # node: ALIAS | ANCHOR? TAG? (SCALAR|sequence|mapping)
241a5f9918aSopenharmony_ci    def parse_node(self):
242a5f9918aSopenharmony_ci        if self.check_token(yaml.AliasToken):
243a5f9918aSopenharmony_ci            self.events.append(yaml.AliasEvent(self.get_token_value(), None, None))
244a5f9918aSopenharmony_ci        else:
245a5f9918aSopenharmony_ci            anchor = None
246a5f9918aSopenharmony_ci            if self.check_token(yaml.AnchorToken):
247a5f9918aSopenharmony_ci                anchor = self.get_token_value()
248a5f9918aSopenharmony_ci            tag = None
249a5f9918aSopenharmony_ci            if self.check_token(yaml.TagToken):
250a5f9918aSopenharmony_ci                tag = self.get_token_value()
251a5f9918aSopenharmony_ci            if self.check_token(yaml.ScalarToken):
252a5f9918aSopenharmony_ci                self.events.append(yaml.ScalarEvent(anchor, tag, (False, False), self.get_token_value(), None, None))
253a5f9918aSopenharmony_ci            elif self.check_token(yaml.FlowSequenceStartToken):
254a5f9918aSopenharmony_ci                self.events.append(yaml.SequenceStartEvent(anchor, tag, None, None))
255a5f9918aSopenharmony_ci                self.parse_sequence()
256a5f9918aSopenharmony_ci            elif self.check_token(yaml.FlowMappingStartToken):
257a5f9918aSopenharmony_ci                self.events.append(yaml.MappingStartEvent(anchor, tag, None, None))
258a5f9918aSopenharmony_ci                self.parse_mapping()
259a5f9918aSopenharmony_ci            else:
260a5f9918aSopenharmony_ci                raise CanonicalError("SCALAR, '[', or '{' is expected, got "+repr(self.tokens[0]))
261a5f9918aSopenharmony_ci
262a5f9918aSopenharmony_ci    # sequence: SEQUENCE-START (node (ENTRY node)*)? ENTRY? SEQUENCE-END
263a5f9918aSopenharmony_ci    def parse_sequence(self):
264a5f9918aSopenharmony_ci        self.get_token(yaml.FlowSequenceStartToken)
265a5f9918aSopenharmony_ci        if not self.check_token(yaml.FlowSequenceEndToken):
266a5f9918aSopenharmony_ci            self.parse_node()
267a5f9918aSopenharmony_ci            while not self.check_token(yaml.FlowSequenceEndToken):
268a5f9918aSopenharmony_ci                self.get_token(yaml.FlowEntryToken)
269a5f9918aSopenharmony_ci                if not self.check_token(yaml.FlowSequenceEndToken):
270a5f9918aSopenharmony_ci                    self.parse_node()
271a5f9918aSopenharmony_ci        self.get_token(yaml.FlowSequenceEndToken)
272a5f9918aSopenharmony_ci        self.events.append(yaml.SequenceEndEvent(None, None))
273a5f9918aSopenharmony_ci
274a5f9918aSopenharmony_ci    # mapping: MAPPING-START (map_entry (ENTRY map_entry)*)? ENTRY? MAPPING-END
275a5f9918aSopenharmony_ci    def parse_mapping(self):
276a5f9918aSopenharmony_ci        self.get_token(yaml.FlowMappingStartToken)
277a5f9918aSopenharmony_ci        if not self.check_token(yaml.FlowMappingEndToken):
278a5f9918aSopenharmony_ci            self.parse_map_entry()
279a5f9918aSopenharmony_ci            while not self.check_token(yaml.FlowMappingEndToken):
280a5f9918aSopenharmony_ci                self.get_token(yaml.FlowEntryToken)
281a5f9918aSopenharmony_ci                if not self.check_token(yaml.FlowMappingEndToken):
282a5f9918aSopenharmony_ci                    self.parse_map_entry()
283a5f9918aSopenharmony_ci        self.get_token(yaml.FlowMappingEndToken)
284a5f9918aSopenharmony_ci        self.events.append(yaml.MappingEndEvent(None, None))
285a5f9918aSopenharmony_ci
286a5f9918aSopenharmony_ci    # map_entry: KEY node VALUE node
287a5f9918aSopenharmony_ci    def parse_map_entry(self):
288a5f9918aSopenharmony_ci        self.get_token(yaml.KeyToken)
289a5f9918aSopenharmony_ci        self.parse_node()
290a5f9918aSopenharmony_ci        self.get_token(yaml.ValueToken)
291a5f9918aSopenharmony_ci        self.parse_node()
292a5f9918aSopenharmony_ci
293a5f9918aSopenharmony_ci    def parse(self):
294a5f9918aSopenharmony_ci        self.parse_stream()
295a5f9918aSopenharmony_ci        self.parsed = True
296a5f9918aSopenharmony_ci
297a5f9918aSopenharmony_ci    def get_event(self):
298a5f9918aSopenharmony_ci        if not self.parsed:
299a5f9918aSopenharmony_ci            self.parse()
300a5f9918aSopenharmony_ci        return self.events.pop(0)
301a5f9918aSopenharmony_ci
302a5f9918aSopenharmony_ci    def check_event(self, *choices):
303a5f9918aSopenharmony_ci        if not self.parsed:
304a5f9918aSopenharmony_ci            self.parse()
305a5f9918aSopenharmony_ci        if self.events:
306a5f9918aSopenharmony_ci            if not choices:
307a5f9918aSopenharmony_ci                return True
308a5f9918aSopenharmony_ci            for choice in choices:
309a5f9918aSopenharmony_ci                if isinstance(self.events[0], choice):
310a5f9918aSopenharmony_ci                    return True
311a5f9918aSopenharmony_ci        return False
312a5f9918aSopenharmony_ci
313a5f9918aSopenharmony_ci    def peek_event(self):
314a5f9918aSopenharmony_ci        if not self.parsed:
315a5f9918aSopenharmony_ci            self.parse()
316a5f9918aSopenharmony_ci        return self.events[0]
317a5f9918aSopenharmony_ci
318a5f9918aSopenharmony_ciclass CanonicalLoader(CanonicalScanner, CanonicalParser,
319a5f9918aSopenharmony_ci        yaml.composer.Composer, yaml.constructor.Constructor, yaml.resolver.Resolver):
320a5f9918aSopenharmony_ci
321a5f9918aSopenharmony_ci    def __init__(self, stream):
322a5f9918aSopenharmony_ci        if hasattr(stream, 'read'):
323a5f9918aSopenharmony_ci            stream = stream.read()
324a5f9918aSopenharmony_ci        CanonicalScanner.__init__(self, stream)
325a5f9918aSopenharmony_ci        CanonicalParser.__init__(self)
326a5f9918aSopenharmony_ci        yaml.composer.Composer.__init__(self)
327a5f9918aSopenharmony_ci        yaml.constructor.Constructor.__init__(self)
328a5f9918aSopenharmony_ci        yaml.resolver.Resolver.__init__(self)
329a5f9918aSopenharmony_ci
330a5f9918aSopenharmony_ciyaml.CanonicalLoader = CanonicalLoader
331a5f9918aSopenharmony_ci
332a5f9918aSopenharmony_cidef canonical_scan(stream):
333a5f9918aSopenharmony_ci    return yaml.scan(stream, Loader=CanonicalLoader)
334a5f9918aSopenharmony_ci
335a5f9918aSopenharmony_ciyaml.canonical_scan = canonical_scan
336a5f9918aSopenharmony_ci
337a5f9918aSopenharmony_cidef canonical_parse(stream):
338a5f9918aSopenharmony_ci    return yaml.parse(stream, Loader=CanonicalLoader)
339a5f9918aSopenharmony_ci
340a5f9918aSopenharmony_ciyaml.canonical_parse = canonical_parse
341a5f9918aSopenharmony_ci
342a5f9918aSopenharmony_cidef canonical_compose(stream):
343a5f9918aSopenharmony_ci    return yaml.compose(stream, Loader=CanonicalLoader)
344a5f9918aSopenharmony_ci
345a5f9918aSopenharmony_ciyaml.canonical_compose = canonical_compose
346a5f9918aSopenharmony_ci
347a5f9918aSopenharmony_cidef canonical_compose_all(stream):
348a5f9918aSopenharmony_ci    return yaml.compose_all(stream, Loader=CanonicalLoader)
349a5f9918aSopenharmony_ci
350a5f9918aSopenharmony_ciyaml.canonical_compose_all = canonical_compose_all
351a5f9918aSopenharmony_ci
352a5f9918aSopenharmony_cidef canonical_load(stream):
353a5f9918aSopenharmony_ci    return yaml.load(stream, Loader=CanonicalLoader)
354a5f9918aSopenharmony_ci
355a5f9918aSopenharmony_ciyaml.canonical_load = canonical_load
356a5f9918aSopenharmony_ci
357a5f9918aSopenharmony_cidef canonical_load_all(stream):
358a5f9918aSopenharmony_ci    return yaml.load_all(stream, Loader=CanonicalLoader)
359a5f9918aSopenharmony_ci
360a5f9918aSopenharmony_ciyaml.canonical_load_all = canonical_load_all
361a5f9918aSopenharmony_ci
362