blob: 95cd6414cf6fabc04dc8735d6ceeedff23797199 [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
Zack Williams1b96a952017-07-17 16:48:01 -070023from yaml.composer import Composer
Zack Williamsbe0b2c72018-01-25 14:48:38 -070024from yaml.constructor import SafeConstructor
Zack Williams1b96a952017-07-17 16:48:01 -070025from yaml.parser import Parser
Zack Williamsbe0b2c72018-01-25 14:48:38 -070026from yaml.reader import Reader
27from yaml.resolver import Resolver
28from yaml.scanner import Scanner
29
Zack Williams1b96a952017-07-17 16:48:01 -070030
31def create_node_class(cls):
32 class node_class(cls):
Zack Williamsbe0b2c72018-01-25 14:48:38 -070033
Zack Williams1b96a952017-07-17 16:48:01 -070034 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
Zack Williamsbe0b2c72018-01-25 14:48:38 -070044
Zack Williams1b96a952017-07-17 16:48:01 -070045dict_node = create_node_class(dict)
46list_node = create_node_class(list)
47unicode_node = create_node_class(unicode)
48int_node = create_node_class(int)
49float_node = create_node_class(float)
50
Zack Williamsbe0b2c72018-01-25 14:48:38 -070051
Zack Williams1b96a952017-07-17 16:48:01 -070052class NodeConstructor(SafeConstructor):
53 # To support lazy loading, the original constructors first yield
54 # an empty object, then fill them in when iterated. Due to
55 # laziness we omit this behaviour (and will only do "deep
56 # construction") by first exhausting iterators, then yielding
57 # copies.
Zack Williamsbe0b2c72018-01-25 14:48:38 -070058
Zack Williams1b96a952017-07-17 16:48:01 -070059 def construct_yaml_map(self, node):
60 obj, = SafeConstructor.construct_yaml_map(self, node)
61 return dict_node(obj, node.start_mark, node.end_mark)
62
63 def construct_yaml_seq(self, node):
64 obj, = SafeConstructor.construct_yaml_seq(self, node)
65 return list_node(obj, node.start_mark, node.end_mark)
66
67 def construct_yaml_str(self, node):
68 obj = SafeConstructor.construct_scalar(self, node)
69 assert isinstance(obj, unicode)
70 return unicode_node(obj, node.start_mark, node.end_mark)
71
72 def construct_yaml_bool(self, node):
73 obj = SafeConstructor.construct_yaml_bool(self, node)
74 return int_node(obj, node.start_mark, node.end_mark)
75
76 def construct_yaml_int(self, node):
77 obj = SafeConstructor.construct_scalar(self, node)
78 return int_node(obj, node.start_mark, node.end_mark)
79
80 def construct_yaml_float(self, node):
81 obj = SafeConstructor.construct_scalar(self, node)
82 return float_node(obj, node.start_mark, node.end_mark)
83
84
85NodeConstructor.add_constructor(
Zack Williamsbe0b2c72018-01-25 14:48:38 -070086 u'tag:yaml.org,2002:map',
87 NodeConstructor.construct_yaml_map)
Zack Williams1b96a952017-07-17 16:48:01 -070088
89NodeConstructor.add_constructor(
Zack Williamsbe0b2c72018-01-25 14:48:38 -070090 u'tag:yaml.org,2002:seq',
91 NodeConstructor.construct_yaml_seq)
Zack Williams1b96a952017-07-17 16:48:01 -070092
93NodeConstructor.add_constructor(
Zack Williamsbe0b2c72018-01-25 14:48:38 -070094 u'tag:yaml.org,2002:str',
95 NodeConstructor.construct_yaml_str)
Zack Williams1b96a952017-07-17 16:48:01 -070096
97NodeConstructor.add_constructor(
Zack Williamsbe0b2c72018-01-25 14:48:38 -070098 u'tag:yaml.org,2002:bool',
99 NodeConstructor.construct_yaml_bool)
Zack Williams1b96a952017-07-17 16:48:01 -0700100
101NodeConstructor.add_constructor(
Zack Williamsbe0b2c72018-01-25 14:48:38 -0700102 u'tag:yaml.org,2002:int',
103 NodeConstructor.construct_yaml_int)
Zack Williams1b96a952017-07-17 16:48:01 -0700104
105NodeConstructor.add_constructor(
Zack Williamsbe0b2c72018-01-25 14:48:38 -0700106 u'tag:yaml.org,2002:float',
107 NodeConstructor.construct_yaml_float)
Zack Williams1b96a952017-07-17 16:48:01 -0700108
109
Zack Williamsbe0b2c72018-01-25 14:48:38 -0700110class MarkedLoader(Reader, Scanner, Parser, Composer,
111 NodeConstructor, Resolver):
112
Zack Williams1b96a952017-07-17 16:48:01 -0700113 def __init__(self, stream):
114 Reader.__init__(self, stream)
115 Scanner.__init__(self)
116 Parser.__init__(self)
117 Composer.__init__(self)
118 NodeConstructor.__init__(self)
119 Resolver.__init__(self)
120
Zack Williamsbe0b2c72018-01-25 14:48:38 -0700121
Zack Williams1b96a952017-07-17 16:48:01 -0700122def get_data(stream):
123 return MarkedLoader(stream).get_data()