7 datetime_available
= True
9 datetime_available
= False
14 from sets
import Set
as set
18 class ConstructorError(MarkedYAMLError
):
21 class BaseConstructor
:
23 def __init__(self
, resolver
):
24 self
.resolver
= resolver
25 self
.constructed_objects
= {}
28 # If there are more documents available?
29 return self
.resolver
.check()
32 # Construct and return the next document.
33 if self
.resolver
.check():
34 return self
.construct_document(self
.resolver
.get())
38 while self
.resolver
.check():
39 yield self
.construct_document(self
.resolver
.get())
41 def construct_document(self
, node
):
42 native
= self
.construct_object(node
)
43 self
.constructed_objects
= {}
46 def construct_object(self
, node
):
47 if node
in self
.constructed_objects
:
48 return self
.constructed_objects
[node
]
49 if node
.tag
in self
.yaml_constructors
:
50 native
= self
.yaml_constructors
[node
.tag
](self
, node
)
51 elif None in self
.yaml_constructors
:
52 native
= self
.yaml_constructors
[None](self
, node
)
53 elif isinstance(node
, ScalarNode
):
54 native
= self
.construct_scalar(node
)
55 elif isinstance(node
, SequenceNode
):
56 native
= self
.construct_sequence(node
)
57 elif isinstance(node
, MappingNode
):
58 native
= self
.construct_mapping(node
)
59 self
.constructed_objects
[node
] = native
62 def construct_scalar(self
, node
):
63 if not isinstance(node
, ScalarNode
):
64 if isinstance(node
, MappingNode
):
65 for key_node
in node
.value
:
66 if key_node
.tag
== u
'tag:yaml.org,2002:value':
67 return self
.construct_scalar(node
.value
[key_node
])
68 raise ConstructorError(None, None,
69 "expected a scalar node, but found %s" % node
.id,
73 def construct_sequence(self
, node
):
74 if not isinstance(node
, SequenceNode
):
75 raise ConstructorError(None, None,
76 "expected a sequence node, but found %s" % node
.id,
78 return [self
.construct_object(child
) for child
in node
.value
]
80 def construct_mapping(self
, node
):
81 if not isinstance(node
, MappingNode
):
82 raise ConstructorError(None, None,
83 "expected a mapping node, but found %s" % node
.id,
86 for key_node
in node
.value
:
87 key
= self
.construct_object(key_node
)
89 duplicate_key
= key
in mapping
90 except TypeError, exc
:
91 raise ConstructorError("while constructing a mapping", node
.start_marker
,
92 "found unacceptable key (%s)" % exc
, key_node
.start_marker
)
94 raise ConstructorError("while constructing a mapping", node
.start_marker
,
95 "found duplicate key", key_node
.start_marker
)
96 value
= self
.construct_object(node
.value
[key_node
])
100 def construct_pairs(self
, node
):
101 if not isinstance(node
, MappingNode
):
102 raise ConstructorError(None, None,
103 "expected a mapping node, but found %s" % node
.id,
106 for key_node
in node
.value
:
107 key
= self
.construct_object(key_node
)
108 value
= self
.construct_object(node
.value
[key_node
])
109 pairs
.append((key
, value
))
112 def add_constructor(cls
, tag
, constructor
):
113 if not 'yaml_constructors' in cls
.__dict
__:
114 cls
.yaml_constructors
= cls
.yaml_constructors
.copy()
115 cls
.yaml_constructors
[tag
] = constructor
116 add_constructor
= classmethod(add_constructor
)
118 yaml_constructors
= {}
120 class Constructor(BaseConstructor
):
122 def construct_yaml_null(self
, node
):
123 self
.construct_scalar(node
)
137 def construct_yaml_bool(self
, node
):
138 value
= self
.construct_scalar(node
)
139 return self
.bool_values
[value
.lower()]
141 def construct_yaml_int(self
, node
):
142 value
= str(self
.construct_scalar(node
))
143 value
= value
.replace('_', '')
151 elif value
.startswith('0b'):
152 return sign
*int(value
[2:], 2)
153 elif value
.startswith('0x'):
154 return sign
*int(value
[2:], 16)
155 elif value
[0] == '0':
156 return sign
*int(value
, 8)
158 digits
= [int(part
) for part
in value
.split(':')]
167 return sign
*int(value
)
170 nan_value
= inf_value
/inf_value
172 def construct_yaml_float(self
, node
):
173 value
= str(self
.construct_scalar(node
))
174 value
= value
.replace('_', '')
180 if value
.lower() == '.inf':
181 return sign
*self
.inf_value
182 elif value
.lower() == '.nan':
183 return self
.nan_value
185 digits
= [float(part
) for part
in value
.split(':')]
196 def construct_yaml_binary(self
, node
):
197 value
= self
.construct_scalar(node
)
199 return str(value
).decode('base64')
200 except (binascii
.Error
, UnicodeEncodeError), exc
:
201 raise ConstructorError(None, None,
202 "failed to decode base64 data: %s" % exc
, node
.start_mark
)
204 def construct_yaml_str(self
, node
):
205 value
= self
.construct_scalar(node
)
208 except UnicodeEncodeError:
211 Constructor
.add_constructor(
212 u
'tag:yaml.org,2002:null',
213 Constructor
.construct_yaml_null
)
215 Constructor
.add_constructor(
216 u
'tag:yaml.org,2002:bool',
217 Constructor
.construct_yaml_bool
)
219 Constructor
.add_constructor(
220 u
'tag:yaml.org,2002:int',
221 Constructor
.construct_yaml_int
)
223 Constructor
.add_constructor(
224 u
'tag:yaml.org,2002:float',
225 Constructor
.construct_yaml_float
)
227 Constructor
.add_constructor(
228 u
'tag:yaml.org,2002:str',
229 Constructor
.construct_yaml_str
)
231 class YAMLObjectMetaclass(type):
233 def __init__(cls
, name
, bases
, kwds
):
234 super(YAMLObjectMetaclass
, cls
).__init
__(name
, bases
, kwds
)
235 if 'yaml_tag' in kwds
and kwds
['yaml_tag'] is not None:
236 cls
.yaml_constructor_class
.add_constructor(cls
.yaml_tag
, cls
.from_yaml
)
238 class YAMLObject(object):
240 __metaclass__
= YAMLObjectMetaclass
242 yaml_constructor_class
= Constructor
246 def from_yaml(cls
, constructor
, node
):
247 raise ConstructorError(None, None,
248 "found undefined constructor for the tag %r"
249 % node
.tag
.encode('utf-8'), node
.start_marker
)
250 from_yaml
= classmethod(from_yaml
)
253 assert False # needs dumper