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'
12try:
13    from .cyaml import *
14    __with_libyaml__ = True
15except ImportError:
16    __with_libyaml__ = False
17
18import io
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        stream = io.StringIO()
204        getvalue = stream.getvalue
205    dumper = Dumper(stream, canonical=canonical, indent=indent, width=width,
206            allow_unicode=allow_unicode, line_break=line_break)
207    try:
208        for event in events:
209            dumper.emit(event)
210    finally:
211        dumper.dispose()
212    if getvalue:
213        return getvalue()
214
215def serialize_all(nodes, stream=None, Dumper=Dumper,
216        canonical=None, indent=None, width=None,
217        allow_unicode=None, line_break=None,
218        encoding=None, explicit_start=None, explicit_end=None,
219        version=None, tags=None):
220    """
221    Serialize a sequence of representation trees into a YAML stream.
222    If stream is None, return the produced string instead.
223    """
224    getvalue = None
225    if stream is None:
226        if encoding is None:
227            stream = io.StringIO()
228        else:
229            stream = io.BytesIO()
230        getvalue = stream.getvalue
231    dumper = Dumper(stream, canonical=canonical, indent=indent, width=width,
232            allow_unicode=allow_unicode, line_break=line_break,
233            encoding=encoding, version=version, tags=tags,
234            explicit_start=explicit_start, explicit_end=explicit_end)
235    try:
236        dumper.open()
237        for node in nodes:
238            dumper.serialize(node)
239        dumper.close()
240    finally:
241        dumper.dispose()
242    if getvalue:
243        return getvalue()
244
245def serialize(node, stream=None, Dumper=Dumper, **kwds):
246    """
247    Serialize a representation tree into a YAML stream.
248    If stream is None, return the produced string instead.
249    """
250    return serialize_all([node], stream, Dumper=Dumper, **kwds)
251
252def dump_all(documents, stream=None, Dumper=Dumper,
253        default_style=None, default_flow_style=False,
254        canonical=None, indent=None, width=None,
255        allow_unicode=None, line_break=None,
256        encoding=None, explicit_start=None, explicit_end=None,
257        version=None, tags=None, sort_keys=True):
258    """
259    Serialize a sequence of Python objects into a YAML stream.
260    If stream is None, return the produced string instead.
261    """
262    getvalue = None
263    if stream is None:
264        if encoding is None:
265            stream = io.StringIO()
266        else:
267            stream = io.BytesIO()
268        getvalue = stream.getvalue
269    dumper = Dumper(stream, default_style=default_style,
270            default_flow_style=default_flow_style,
271            canonical=canonical, indent=indent, width=width,
272            allow_unicode=allow_unicode, line_break=line_break,
273            encoding=encoding, version=version, tags=tags,
274            explicit_start=explicit_start, explicit_end=explicit_end, sort_keys=sort_keys)
275    try:
276        dumper.open()
277        for data in documents:
278            dumper.represent(data)
279        dumper.close()
280    finally:
281        dumper.dispose()
282    if getvalue:
283        return getvalue()
284
285def dump(data, stream=None, Dumper=Dumper, **kwds):
286    """
287    Serialize a Python object into a YAML stream.
288    If stream is None, return the produced string instead.
289    """
290    return dump_all([data], stream, Dumper=Dumper, **kwds)
291
292def safe_dump_all(documents, stream=None, **kwds):
293    """
294    Serialize a sequence of Python objects into a YAML stream.
295    Produce only basic YAML tags.
296    If stream is None, return the produced string instead.
297    """
298    return dump_all(documents, stream, Dumper=SafeDumper, **kwds)
299
300def safe_dump(data, stream=None, **kwds):
301    """
302    Serialize a Python object into a YAML stream.
303    Produce only basic YAML tags.
304    If stream is None, return the produced string instead.
305    """
306    return dump_all([data], stream, Dumper=SafeDumper, **kwds)
307
308def add_implicit_resolver(tag, regexp, first=None,
309        Loader=None, Dumper=Dumper):
310    """
311    Add an implicit scalar detector.
312    If an implicit scalar value matches the given regexp,
313    the corresponding tag is assigned to the scalar.
314    first is a sequence of possible initial characters or None.
315    """
316    if Loader is None:
317        loader.Loader.add_implicit_resolver(tag, regexp, first)
318        loader.FullLoader.add_implicit_resolver(tag, regexp, first)
319        loader.UnsafeLoader.add_implicit_resolver(tag, regexp, first)
320    else:
321        Loader.add_implicit_resolver(tag, regexp, first)
322    Dumper.add_implicit_resolver(tag, regexp, first)
323
324def add_path_resolver(tag, path, kind=None, Loader=None, Dumper=Dumper):
325    """
326    Add a path based resolver for the given tag.
327    A path is a list of keys that forms a path
328    to a node in the representation tree.
329    Keys can be string values, integers, or None.
330    """
331    if Loader is None:
332        loader.Loader.add_path_resolver(tag, path, kind)
333        loader.FullLoader.add_path_resolver(tag, path, kind)
334        loader.UnsafeLoader.add_path_resolver(tag, path, kind)
335    else:
336        Loader.add_path_resolver(tag, path, kind)
337    Dumper.add_path_resolver(tag, path, kind)
338
339def add_constructor(tag, constructor, Loader=None):
340    """
341    Add a constructor for the given tag.
342    Constructor is a function that accepts a Loader instance
343    and a node object and produces the corresponding Python object.
344    """
345    if Loader is None:
346        loader.Loader.add_constructor(tag, constructor)
347        loader.FullLoader.add_constructor(tag, constructor)
348        loader.UnsafeLoader.add_constructor(tag, constructor)
349    else:
350        Loader.add_constructor(tag, constructor)
351
352def add_multi_constructor(tag_prefix, multi_constructor, Loader=None):
353    """
354    Add a multi-constructor for the given tag prefix.
355    Multi-constructor is called for a node if its tag starts with tag_prefix.
356    Multi-constructor accepts a Loader instance, a tag suffix,
357    and a node object and produces the corresponding Python object.
358    """
359    if Loader is None:
360        loader.Loader.add_multi_constructor(tag_prefix, multi_constructor)
361        loader.FullLoader.add_multi_constructor(tag_prefix, multi_constructor)
362        loader.UnsafeLoader.add_multi_constructor(tag_prefix, multi_constructor)
363    else:
364        Loader.add_multi_constructor(tag_prefix, multi_constructor)
365
366def add_representer(data_type, representer, Dumper=Dumper):
367    """
368    Add a representer for the given type.
369    Representer is a function accepting a Dumper instance
370    and an instance of the given data type
371    and producing the corresponding representation node.
372    """
373    Dumper.add_representer(data_type, representer)
374
375def add_multi_representer(data_type, multi_representer, Dumper=Dumper):
376    """
377    Add a representer for the given type.
378    Multi-representer is a function accepting a Dumper instance
379    and an instance of the given data type or subtype
380    and producing the corresponding representation node.
381    """
382    Dumper.add_multi_representer(data_type, multi_representer)
383
384class YAMLObjectMetaclass(type):
385    """
386    The metaclass for YAMLObject.
387    """
388    def __init__(cls, name, bases, kwds):
389        super(YAMLObjectMetaclass, cls).__init__(name, bases, kwds)
390        if 'yaml_tag' in kwds and kwds['yaml_tag'] is not None:
391            if isinstance(cls.yaml_loader, list):
392                for loader in cls.yaml_loader:
393                    loader.add_constructor(cls.yaml_tag, cls.from_yaml)
394            else:
395                cls.yaml_loader.add_constructor(cls.yaml_tag, cls.from_yaml)
396
397            cls.yaml_dumper.add_representer(cls, cls.to_yaml)
398
399class YAMLObject(metaclass=YAMLObjectMetaclass):
400    """
401    An object that can dump itself to a YAML stream
402    and load itself from a YAML stream.
403    """
404
405    __slots__ = ()  # no direct instantiation, so allow immutable subclasses
406
407    yaml_loader = [Loader, FullLoader, UnsafeLoader]
408    yaml_dumper = Dumper
409
410    yaml_tag = None
411    yaml_flow_style = None
412
413    @classmethod
414    def from_yaml(cls, loader, node):
415        """
416        Convert a representation node to a Python object.
417        """
418        return loader.construct_yaml_object(node, cls)
419
420    @classmethod
421    def to_yaml(cls, dumper, data):
422        """
423        Convert a Python object to a representation node.
424        """
425        return dumper.represent_yaml_object(cls.yaml_tag, data, cls,
426                flow_style=cls.yaml_flow_style)
427
428