blob: f7c14841a795496b99467885ed11ec9bb0875fcc [file] [log] [blame]
Zack Williams1b96a952017-07-17 16:48:01 -07001# Copyright 2017-present Open Networking Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15# markedyaml.py
16# generates nodes with start/end line and column values
17# start line seems off with single-line items, correct with multiline
18#
19# Original code from here: https://gist.github.com/dagss/5008118
20# Request for licensing clarification made on 2017-09-19
21# Contains improvements to support more types (bool/int/etc.)
22
23import yaml
24from yaml.composer import Composer
25from yaml.reader import Reader
26from yaml.scanner import Scanner
27from yaml.composer import Composer
28from yaml.resolver import Resolver
29from yaml.parser import Parser
30from yaml.constructor import Constructor, BaseConstructor, SafeConstructor
31
32def create_node_class(cls):
33 class node_class(cls):
34 def __init__(self, x, start_mark, end_mark):
35 cls.__init__(self, x)
36 self.start_mark = start_mark
37 self.end_mark = end_mark
38
39 def __new__(self, x, start_mark, end_mark):
40 return cls.__new__(self, x)
41 node_class.__name__ = '%s_node' % cls.__name__
42 return node_class
43
44dict_node = create_node_class(dict)
45list_node = create_node_class(list)
46unicode_node = create_node_class(unicode)
47int_node = create_node_class(int)
48float_node = create_node_class(float)
49
50class NodeConstructor(SafeConstructor):
51 # To support lazy loading, the original constructors first yield
52 # an empty object, then fill them in when iterated. Due to
53 # laziness we omit this behaviour (and will only do "deep
54 # construction") by first exhausting iterators, then yielding
55 # copies.
56 def construct_yaml_map(self, node):
57 obj, = SafeConstructor.construct_yaml_map(self, node)
58 return dict_node(obj, node.start_mark, node.end_mark)
59
60 def construct_yaml_seq(self, node):
61 obj, = SafeConstructor.construct_yaml_seq(self, node)
62 return list_node(obj, node.start_mark, node.end_mark)
63
64 def construct_yaml_str(self, node):
65 obj = SafeConstructor.construct_scalar(self, node)
66 assert isinstance(obj, unicode)
67 return unicode_node(obj, node.start_mark, node.end_mark)
68
69 def construct_yaml_bool(self, node):
70 obj = SafeConstructor.construct_yaml_bool(self, node)
71 return int_node(obj, node.start_mark, node.end_mark)
72
73 def construct_yaml_int(self, node):
74 obj = SafeConstructor.construct_scalar(self, node)
75 return int_node(obj, node.start_mark, node.end_mark)
76
77 def construct_yaml_float(self, node):
78 obj = SafeConstructor.construct_scalar(self, node)
79 return float_node(obj, node.start_mark, node.end_mark)
80
81
82NodeConstructor.add_constructor(
83 u'tag:yaml.org,2002:map',
84 NodeConstructor.construct_yaml_map)
85
86NodeConstructor.add_constructor(
87 u'tag:yaml.org,2002:seq',
88 NodeConstructor.construct_yaml_seq)
89
90NodeConstructor.add_constructor(
91 u'tag:yaml.org,2002:str',
92 NodeConstructor.construct_yaml_str)
93
94NodeConstructor.add_constructor(
95 u'tag:yaml.org,2002:bool',
96 NodeConstructor.construct_yaml_bool)
97
98NodeConstructor.add_constructor(
99 u'tag:yaml.org,2002:int',
100 NodeConstructor.construct_yaml_int)
101
102NodeConstructor.add_constructor(
103 u'tag:yaml.org,2002:float',
104 NodeConstructor.construct_yaml_float)
105
106
107class MarkedLoader(Reader, Scanner, Parser, Composer, NodeConstructor, Resolver):
108 def __init__(self, stream):
109 Reader.__init__(self, stream)
110 Scanner.__init__(self)
111 Parser.__init__(self)
112 Composer.__init__(self)
113 NodeConstructor.__init__(self)
114 Resolver.__init__(self)
115
116def get_data(stream):
117 return MarkedLoader(stream).get_data()
118