1
2from error import *
3
4from tokens import *
5from events import *
6from nodes import *
7
8from loader import *
9from dumper import *
10
11__version__ = '5.4.1'
12
13try:
14    from cyaml import *
15    __with_libyaml__ = True
16except ImportError:
17    __with_libyaml__ = False
18
19
20#------------------------------------------------------------------------------
21# Warnings control
22#------------------------------------------------------------------------------
23
24# 'Global' warnings state:
25_warnings_enabled = {
26    'YAMLLoadWarning': True,
27}
28
29# Get or set global warnings' state
30def warnings(settings=None):
31    if settings is None:
32        return _warnings_enabled
33
34    if type(settings) is dict:
35        for key in settings:
36            if key in _warnings_enabled:
37                _warnings_enabled[key] = settings[key]
38
39# Warn when load() is called without Loader=...
40class YAMLLoadWarning(RuntimeWarning):
41    pass
42
43def load_warning(method):
44    if _warnings_enabled['YAMLLoadWarning'] is False:
45        return
46
47    import warnings
48
49    message = (
50        "calling yaml.%s() without Loader=... is deprecated, as the "
51        "default Loader is unsafe. Please read "
52        "https://msg.pyyaml.org/load for full details."
53    ) % method
54
55    warnings.warn(message, YAMLLoadWarning, stacklevel=3)
56
57#------------------------------------------------------------------------------
58def scan(stream, Loader=Loader):
59    """
60    Scan a YAML stream and produce scanning tokens.
61    """
62    loader = Loader(stream)
63    try:
64        while loader.check_token():
65            yield loader.get_token()
66    finally:
67        loader.dispose()
68
69def parse(stream, Loader=Loader):
70    """
71    Parse a YAML stream and produce parsing events.
72    """
73    loader = Loader(stream)
74    try:
75        while loader.check_event():
76            yield loader.get_event()
77    finally:
78        loader.dispose()
79
80def compose(stream, Loader=Loader):
81    """
82    Parse the first YAML document in a stream
83    and produce the corresponding representation tree.
84    """
85    loader = Loader(stream)
86    try:
87        return loader.get_single_node()
88    finally:
89        loader.dispose()
90
91def compose_all(stream, Loader=Loader):
92    """
93    Parse all YAML documents in a stream
94    and produce corresponding representation trees.
95    """
96    loader = Loader(stream)
97    try:
98        while loader.check_node():
99            yield loader.get_node()
100    finally:
101        loader.dispose()
102
103def load(stream, Loader=None):
104    """
105    Parse the first YAML document in a stream
106    and produce the corresponding Python object.
107    """
108    if Loader is None:
109        load_warning('load')
110        Loader = FullLoader
111
112    loader = Loader(stream)
113    try:
114        return loader.get_single_data()
115    finally:
116        loader.dispose()
117
118def load_all(stream, Loader=None):
119    """
120    Parse all YAML documents in a stream
121    and produce corresponding Python objects.
122    """
123    if Loader is None:
124        load_warning('load_all')
125        Loader = FullLoader
126
127    loader = Loader(stream)
128    try:
129        while loader.check_data():
130            yield loader.get_data()
131    finally:
132        loader.dispose()
133
134def full_load(stream):
135    """
136    Parse the first YAML document in a stream
137    and produce the corresponding Python object.
138
139    Resolve all tags except those known to be
140    unsafe on untrusted input.
141    """
142    return load(stream, FullLoader)
143
144def full_load_all(stream):
145    """
146    Parse all YAML documents in a stream
147    and produce corresponding Python objects.
148
149    Resolve all tags except those known to be
150    unsafe on untrusted input.
151    """
152    return load_all(stream, FullLoader)
153
154def safe_load(stream):
155    """
156    Parse the first YAML document in a stream
157    and produce the corresponding Python object.
158
159    Resolve only basic YAML tags. This is known
160    to be safe for untrusted input.
161    """
162    return load(stream, SafeLoader)
163
164def safe_load_all(stream):
165    """
166    Parse all YAML documents in a stream
167    and produce corresponding Python objects.
168
169    Resolve only basic YAML tags. This is known
170    to be safe for untrusted input.
171    """
172    return load_all(stream, SafeLoader)
173
174def unsafe_load(stream):
175    """
176    Parse the first YAML document in a stream
177    and produce the corresponding Python object.
178
179    Resolve all tags, even those known to be
180    unsafe on untrusted input.
181    """
182    return load(stream, UnsafeLoader)
183
184def unsafe_load_all(stream):
185    """
186    Parse all YAML documents in a stream
187    and produce corresponding Python objects.
188
189    Resolve all tags, even those known to be
190    unsafe on untrusted input.
191    """
192    return load_all(stream, UnsafeLoader)
193
194def emit(events, stream=None, Dumper=Dumper,
195        canonical=None, indent=None, width=None,
196        allow_unicode=None, line_break=None):
197    """
198    Emit YAML parsing events into a stream.
199    If stream is None, return the produced string instead.
200    """
201    getvalue = None
202    if stream is None:
203        from StringIO import StringIO
204        stream = StringIO()
205        getvalue = stream.getvalue
206    dumper = Dumper(stream, canonical=canonical, indent=indent, width=width,
207            allow_unicode=allow_unicode, line_break=line_break)
208    try:
209        for event in events:
210            dumper.emit(event)
211    finally:
212        dumper.dispose()
213    if getvalue:
214        return getvalue()
215
216def serialize_all(nodes, stream=None, Dumper=Dumper,
217        canonical=None, indent=None, width=None,
218        allow_unicode=None, line_break=None,
219        encoding='utf-8', explicit_start=None, explicit_end=None,
220        version=None, tags=None):
221    """
222    Serialize a sequence of representation trees into a YAML stream.
223    If stream is None, return the produced string instead.
224    """
225    getvalue = None
226    if stream is None:
227        if encoding is None:
228            from StringIO import StringIO
229        else:
230            from cStringIO import StringIO
231        stream = StringIO()
232        getvalue = stream.getvalue
233    dumper = Dumper(stream, canonical=canonical, indent=indent, width=width,
234            allow_unicode=allow_unicode, line_break=line_break,
235            encoding=encoding, version=version, tags=tags,
236            explicit_start=explicit_start, explicit_end=explicit_end)
237    try:
238        dumper.open()
239        for node in nodes:
240            dumper.serialize(node)
241        dumper.close()
242    finally:
243        dumper.dispose()
244    if getvalue:
245        return getvalue()
246
247def serialize(node, stream=None, Dumper=Dumper, **kwds):
248    """
249    Serialize a representation tree into a YAML stream.
250    If stream is None, return the produced string instead.
251    """
252    return serialize_all([node], stream, Dumper=Dumper, **kwds)
253
254def dump_all(documents, stream=None, Dumper=Dumper,
255        default_style=None, default_flow_style=False,
256        canonical=None, indent=None, width=None,
257        allow_unicode=None, line_break=None,
258        encoding='utf-8', explicit_start=None, explicit_end=None,
259        version=None, tags=None, sort_keys=True):
260    """
261    Serialize a sequence of Python objects into a YAML stream.
262    If stream is None, return the produced string instead.
263    """
264    getvalue = None
265    if stream is None:
266        if encoding is None:
267            from StringIO import StringIO
268        else:
269            from cStringIO import StringIO
270        stream = StringIO()
271        getvalue = stream.getvalue
272    dumper = Dumper(stream, default_style=default_style,
273            default_flow_style=default_flow_style,
274            canonical=canonical, indent=indent, width=width,
275            allow_unicode=allow_unicode, line_break=line_break,
276            encoding=encoding, version=version, tags=tags,
277            explicit_start=explicit_start, explicit_end=explicit_end, sort_keys=sort_keys)
278    try:
279        dumper.open()
280        for data in documents:
281            dumper.represent(data)
282        dumper.close()
283    finally:
284        dumper.dispose()
285    if getvalue:
286        return getvalue()
287
288def dump(data, stream=None, Dumper=Dumper, **kwds):
289    """
290    Serialize a Python object into a YAML stream.
291    If stream is None, return the produced string instead.
292    """
293    return dump_all([data], stream, Dumper=Dumper, **kwds)
294
295def safe_dump_all(documents, stream=None, **kwds):
296    """
297    Serialize a sequence of Python objects into a YAML stream.
298    Produce only basic YAML tags.
299    If stream is None, return the produced string instead.
300    """
301    return dump_all(documents, stream, Dumper=SafeDumper, **kwds)
302
303def safe_dump(data, stream=None, **kwds):
304    """
305    Serialize a Python object into a YAML stream.
306    Produce only basic YAML tags.
307    If stream is None, return the produced string instead.
308    """
309    return dump_all([data], stream, Dumper=SafeDumper, **kwds)
310
311def add_implicit_resolver(tag, regexp, first=None,
312        Loader=None, Dumper=Dumper):
313    """
314    Add an implicit scalar detector.
315    If an implicit scalar value matches the given regexp,
316    the corresponding tag is assigned to the scalar.
317    first is a sequence of possible initial characters or None.
318    """
319    if Loader is None:
320        loader.Loader.add_implicit_resolver(tag, regexp, first)
321        loader.FullLoader.add_implicit_resolver(tag, regexp, first)
322        loader.UnsafeLoader.add_implicit_resolver(tag, regexp, first)
323    else:
324        Loader.add_implicit_resolver(tag, regexp, first)
325    Dumper.add_implicit_resolver(tag, regexp, first)
326
327def add_path_resolver(tag, path, kind=None, Loader=None, Dumper=Dumper):
328    """
329    Add a path based resolver for the given tag.
330    A path is a list of keys that forms a path
331    to a node in the representation tree.
332    Keys can be string values, integers, or None.
333    """
334    if Loader is None:
335        loader.Loader.add_path_resolver(tag, path, kind)
336        loader.FullLoader.add_path_resolver(tag, path, kind)
337        loader.UnsafeLoader.add_path_resolver(tag, path, kind)
338    else:
339        Loader.add_path_resolver(tag, path, kind)
340    Dumper.add_path_resolver(tag, path, kind)
341
342def add_constructor(tag, constructor, Loader=None):
343    """
344    Add a constructor for the given tag.
345    Constructor is a function that accepts a Loader instance
346    and a node object and produces the corresponding Python object.
347    """
348    if Loader is None:
349        loader.Loader.add_constructor(tag, constructor)
350        loader.FullLoader.add_constructor(tag, constructor)
351        loader.UnsafeLoader.add_constructor(tag, constructor)
352    else:
353        Loader.add_constructor(tag, constructor)
354
355def add_multi_constructor(tag_prefix, multi_constructor, Loader=None):
356    """
357    Add a multi-constructor for the given tag prefix.
358    Multi-constructor is called for a node if its tag starts with tag_prefix.
359    Multi-constructor accepts a Loader instance, a tag suffix,
360    and a node object and produces the corresponding Python object.
361    """
362    if Loader is None:
363        loader.Loader.add_multi_constructor(tag_prefix, multi_constructor)
364        loader.FullLoader.add_multi_constructor(tag_prefix, multi_constructor)
365        loader.UnsafeLoader.add_multi_constructor(tag_prefix, multi_constructor)
366    else:
367        Loader.add_multi_constructor(tag_prefix, multi_constructor)
368
369def add_representer(data_type, representer, Dumper=Dumper):
370    """
371    Add a representer for the given type.
372    Representer is a function accepting a Dumper instance
373    and an instance of the given data type
374    and producing the corresponding representation node.
375    """
376    Dumper.add_representer(data_type, representer)
377
378def add_multi_representer(data_type, multi_representer, Dumper=Dumper):
379    """
380    Add a representer for the given type.
381    Multi-representer is a function accepting a Dumper instance
382    and an instance of the given data type or subtype
383    and producing the corresponding representation node.
384    """
385    Dumper.add_multi_representer(data_type, multi_representer)
386
387class YAMLObjectMetaclass(type):
388    """
389    The metaclass for YAMLObject.
390    """
391    def __init__(cls, name, bases, kwds):
392        super(YAMLObjectMetaclass, cls).__init__(name, bases, kwds)
393        if 'yaml_tag' in kwds and kwds['yaml_tag'] is not None:
394            if isinstance(cls.yaml_loader, list):
395                for loader in cls.yaml_loader:
396                    loader.add_constructor(cls.yaml_tag, cls.from_yaml)
397            else:
398                cls.yaml_loader.add_constructor(cls.yaml_tag, cls.from_yaml)
399
400            cls.yaml_dumper.add_representer(cls, cls.to_yaml)
401
402class YAMLObject(object):
403    """
404    An object that can dump itself to a YAML stream
405    and load itself from a YAML stream.
406    """
407
408    __metaclass__ = YAMLObjectMetaclass
409    __slots__ = ()  # no direct instantiation, so allow immutable subclasses
410
411    yaml_loader = [Loader, FullLoader, UnsafeLoader]
412    yaml_dumper = Dumper
413
414    yaml_tag = None
415    yaml_flow_style = None
416
417    def from_yaml(cls, loader, node):
418        """
419        Convert a representation node to a Python object.
420        """
421        return loader.construct_yaml_object(node, cls)
422    from_yaml = classmethod(from_yaml)
423
424    def to_yaml(cls, dumper, data):
425        """
426        Convert a Python object to a representation node.
427        """
428        return dumper.represent_yaml_object(cls.yaml_tag, data, cls,
429                flow_style=cls.yaml_flow_style)
430    to_yaml = classmethod(to_yaml)
431
432