summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthon van der Neut <anthon@mnt.org>2018-08-05 23:20:17 +0200
committerAnthon van der Neut <anthon@mnt.org>2018-08-05 23:20:17 +0200
commitbfd63d6184e3a43cb63e0831467819bc44513d50 (patch)
tree9426b3c93cb1fd7849ea678424b6bbd900ff2d68
parent893db272efb6d7041e09aa09f04da2010ec92072 (diff)
downloadruamel.yaml-bfd63d6184e3a43cb63e0831467819bc44513d50.tar.gz
added context manager, mypy cleanup (w. Optional) added tests0.15.50
-rw-r--r--CHANGES6
-rw-r--r--README.rst8
-rw-r--r--__init__.py4
-rw-r--r--_doc/_static/pypi.svg2
-rw-r--r--_doc/api.ryd56
-rw-r--r--_doc/basicuse.ryd2
-rw-r--r--_test/test_contextmanager.py12
-rw-r--r--comments.py4
-rw-r--r--compat.py4
-rw-r--r--constructor.py4
-rw-r--r--cyaml.py14
-rw-r--r--dumper.py10
-rw-r--r--emitter.py12
-rw-r--r--loader.py10
-rw-r--r--main.py103
-rw-r--r--reader.py12
-rw-r--r--representer.py4
-rw-r--r--resolver.py6
-rw-r--r--serializer.py6
19 files changed, 196 insertions, 83 deletions
diff --git a/CHANGES b/CHANGES
index eadd88a..f9c160f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+[0, 15, 50]: 2018-08-05
+ - Allow ``YAML()`` as a context manager for output, thereby making it much easier
+ to generate multi-documents in a stream.
+ - Fix issue with incorrect type information for `load()` and `dump()` (reported
+ by `Jimbo Jim <https://bitbucket.org/jimbo1qaz/>`__)
+
[0, 15, 49]: 2018-08-05
- fix preservation of leading newlines in root level literal style scalar,
and preserve comment after literal style indicator (``| # some comment``)
diff --git a/README.rst b/README.rst
index 8f540c3..0af8415 100644
--- a/README.rst
+++ b/README.rst
@@ -4,7 +4,7 @@ ruamel.yaml
``ruamel.yaml`` is a YAML 1.2 loader/dumper package for Python.
-:version: 0.15.49
+:version: 0.15.50
:updated: 2018-08-05
:documentation: http://yaml.readthedocs.io
:repository: https://bitbucket.org/ruamel/
@@ -54,6 +54,12 @@ ChangeLog
.. should insert NEXT: at the beginning of line for next key (with empty line)
+0.15.50 (2018-08-05):
+ - Allow ``YAML()`` as a context manager for output, thereby making it much easier
+ to generate multi-documents in a stream.
+ - Fix issue with incorrect type information for `load()` and `dump()` (reported
+ by `Jimbo Jim <https://bitbucket.org/jimbo1qaz/>`__)
+
0.15.49 (2018-08-05):
- fix preservation of leading newlines in root level literal style scalar,
and preserve comment after literal style indicator (``| # some comment``)
diff --git a/__init__.py b/__init__.py
index ece2b5b..1e3bf42 100644
--- a/__init__.py
+++ b/__init__.py
@@ -7,8 +7,8 @@ if False: # MYPY
_package_data = dict(
full_package_name='ruamel.yaml',
- version_info=(0, 15, 50, 'dev'),
- __version__='0.15.50.dev',
+ version_info=(0, 15, 50),
+ __version__='0.15.50',
author='Anthon van der Neut',
author_email='a.van.der.neut@ruamel.eu',
description='ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order', # NOQA
diff --git a/_doc/_static/pypi.svg b/_doc/_static/pypi.svg
index 67703ce..a145534 100644
--- a/_doc/_static/pypi.svg
+++ b/_doc/_static/pypi.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="86" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h33v20H0z"/><path fill="#007ec6" d="M33 0h53v20H33z"/><path fill="url(#b)" d="M0 0h86v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"> <text x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="230">pypi</text><text x="175" y="140" transform="scale(.1)" textLength="230">pypi</text><text x="585" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">0.15.49</text><text x="585" y="140" transform="scale(.1)" textLength="430">0.15.49</text></g> </svg>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="86" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h33v20H0z"/><path fill="#007ec6" d="M33 0h53v20H33z"/><path fill="url(#b)" d="M0 0h86v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"> <text x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="230">pypi</text><text x="175" y="140" transform="scale(.1)" textLength="230">pypi</text><text x="585" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">0.15.50</text><text x="585" y="140" transform="scale(.1)" textLength="430">0.15.50</text></g> </svg>
diff --git a/_doc/api.ryd b/_doc/api.ryd
index a6c5afd..9e89b00 100644
--- a/_doc/api.ryd
+++ b/_doc/api.ryd
@@ -116,6 +116,62 @@ yaml.load(stream)
In the old API this is a warning starting with 0.15.2 and an error in
0.16.0.
+Dumping a multi-documents YAML stream
++++++++++++++++++++++++++++++++++++++
+
+The "normal" ``dump_all`` expected as first element a list of documents, or
+something else the internals of the method can iterate over. To read
+and write a multi-document you would either make a ``list``::
+
+--- !code |
+ yaml = YAML()
+ data = list(yaml.load_all(in_path))
+ # do something on data[0], data[1], etc.
+ yaml.dump_all(data, out_path)
+--- |
+
+or create some function/object that would yield the ``data`` values.
+
+What you now can do is create ``YAML()`` as an context manager. This
+works for output (dumping) only, requires you to specify the output
+(file, buffer, ``Path``) at creation time, and doesn't support
+``transform`` (yet).
+
+::
+
+--- !code |
+ with YAML(output=sys.stdout) as yaml:
+ yaml.explicit_start = True
+ for data in yaml.load_all(Path(multi_document_filename)):
+ # do something on data
+ yaml.dump(data)
+--- |
+
+Within the context manager, you cannot use the ``dump()`` with a
+second (stream) argument, nor can you use ``dump_all()``. The
+``dump()`` within the context of the ``YAML()`` automatically creates
+ multi-document if called more than once.
+
+To combine multiple YAML documents from multiple files:
+
+::
+
+--- !code |
+ list_of_filenames = ['x.yaml', 'y.yaml', ]
+ with YAML(output=sys.stdout) as yaml:
+ yaml.explicit_start = True
+ for path in list_of_filename:
+ with open(path) as fp:
+ yaml.dump(yaml.load(fp))
+--- |
+
+The output will be a valid, uniformly indented YAML file. Doing
+``cat {x,y}.yaml`` might result in a single document if there is not
+document start marker at the beginning of ``y.yaml``
+
+
+
+
Dumping
+++++++
diff --git a/_doc/basicuse.ryd b/_doc/basicuse.ryd
index c4a744d..9d2512d 100644
--- a/_doc/basicuse.ryd
+++ b/_doc/basicuse.ryd
@@ -38,7 +38,7 @@ enforce using the pure Python implementation (faster C libraries will be used
when possible/available)
Dumping works in the same way::
---- !python |
+--- !code |
from ruamel.yaml import YAML
yaml=YAML()
diff --git a/_test/test_contextmanager.py b/_test/test_contextmanager.py
index 85adf75..76d24aa 100644
--- a/_test/test_contextmanager.py
+++ b/_test/test_contextmanager.py
@@ -98,3 +98,15 @@ class TestContextManager:
# with YAML(input=multi_doc) as yaml:
# for idx, data in enumerate(yaml.load()):
# assert data == multi_doc_data[0]
+
+ def test_roundtrip(self, capsys):
+ from ruamel.yaml import YAML
+
+ with YAML(output=sys.stdout) as yaml:
+ yaml.explicit_start = True
+ for data in yaml.load_all(multi_doc):
+ yaml.dump(data)
+
+ out, err = capsys.readouterr()
+ print(err)
+ assert out == multi_doc
diff --git a/comments.py b/comments.py
index 32ce8ce..84fecbc 100644
--- a/comments.py
+++ b/comments.py
@@ -21,7 +21,7 @@ else:
from collections.abc import MutableSet, Sized, Set
if False: # MYPY
- from typing import Any, Dict, Optional, List, Union # NOQA
+ from typing import Any, Dict, Optional, List, Union, Optional # NOQA
# fmt: off
__all__ = ["CommentedSeq", "CommentedKeySeq",
@@ -127,7 +127,7 @@ class LineCol(object):
# type: () -> None
self.line = None
self.col = None
- self.data = None # type: Union[None, Dict[Any, Any]]
+ self.data = None # type: Optional[Dict[Any, Any]]
def add_kv_line_col(self, key, data):
# type: (Any, Any) -> None
diff --git a/compat.py b/compat.py
index a962103..3eb6464 100644
--- a/compat.py
+++ b/compat.py
@@ -9,7 +9,7 @@ import os
import types
if False: # MYPY
- from typing import Any, Dict, Optional, List, Union, BinaryIO, IO, Text, Tuple # NOQA
+ from typing import Any, Dict, Optional, List, Union, BinaryIO, IO, Text, Tuple, Optional # NOQA
_DEFAULT_YAML_VERSION = (1, 2)
@@ -136,7 +136,7 @@ DBG_EVENT = 2
DBG_NODE = 4
-_debug = None # type: Union[None, int]
+_debug = None # type: Optional[int]
if 'RUAMELDEBUG' in os.environ:
_debugx = os.environ.get('RUAMELDEBUG')
if _debugx is None:
diff --git a/constructor.py b/constructor.py
index c36f01d..6de5181 100644
--- a/constructor.py
+++ b/constructor.py
@@ -29,7 +29,7 @@ from ruamel.yaml.timestamp import TimeStamp
from ruamel.yaml.util import RegExp
if False: # MYPY
- from typing import Any, Dict, List, Set, Generator, Union # NOQA
+ from typing import Any, Dict, List, Set, Generator, Union, Optional # NOQA
__all__ = ['BaseConstructor', 'SafeConstructor', 'Constructor',
@@ -55,7 +55,7 @@ class BaseConstructor(object):
yaml_multi_constructors = {} # type: Dict[Any, Any]
def __init__(self, preserve_quotes=None, loader=None):
- # type: (Union[None, bool], Any) -> None
+ # type: (Optional[bool], Any) -> None
self.loader = loader
if self.loader is not None and getattr(self.loader, '_constructor', None) is None:
self.loader._constructor = self
diff --git a/cyaml.py b/cyaml.py
index ed2c1da..3e013cb 100644
--- a/cyaml.py
+++ b/cyaml.py
@@ -9,7 +9,7 @@ from ruamel.yaml.representer import Representer, SafeRepresenter, BaseRepresente
from ruamel.yaml.resolver import Resolver, BaseResolver
if False: # MYPY
- from typing import Any, Union # NOQA
+ from typing import Any, Union, Optional # NOQA
from ruamel.yaml.compat import StreamTextType, StreamType, VersionType # NOQA
__all__ = ['CBaseLoader', 'CSafeLoader', 'CLoader', 'CBaseDumper', 'CSafeDumper', 'CDumper']
@@ -21,7 +21,7 @@ __all__ = ['CBaseLoader', 'CSafeLoader', 'CLoader', 'CBaseDumper', 'CSafeDumper'
class CBaseLoader(CParser, BaseConstructor, BaseResolver): # type: ignore
def __init__(self, stream, version=None, preserve_quotes=None):
- # type: (StreamTextType, Union[None, VersionType], Union[None, bool]) -> None
+ # type: (StreamTextType, Optional[VersionType], Optional[bool]) -> None
CParser.__init__(self, stream)
self._parser = self._composer = self
BaseConstructor.__init__(self, loader=self)
@@ -33,7 +33,7 @@ class CBaseLoader(CParser, BaseConstructor, BaseResolver): # type: ignore
class CSafeLoader(CParser, SafeConstructor, Resolver): # type: ignore
def __init__(self, stream, version=None, preserve_quotes=None):
- # type: (StreamTextType, Union[None, VersionType], Union[None, bool]) -> None
+ # type: (StreamTextType, Optional[VersionType], Optional[bool]) -> None
CParser.__init__(self, stream)
self._parser = self._composer = self
SafeConstructor.__init__(self, loader=self)
@@ -45,7 +45,7 @@ class CSafeLoader(CParser, SafeConstructor, Resolver): # type: ignore
class CLoader(CParser, Constructor, Resolver): # type: ignore
def __init__(self, stream, version=None, preserve_quotes=None):
- # type: (StreamTextType, Union[None, VersionType], Union[None, bool]) -> None
+ # type: (StreamTextType, Optional[VersionType], Optional[bool]) -> None
CParser.__init__(self, stream)
self._parser = self._composer = self
Constructor.__init__(self, loader=self)
@@ -75,7 +75,7 @@ class CBaseDumper(CEmitter, BaseRepresenter, BaseResolver): # type: ignore
top_level_colon_align=None,
prefix_colon=None,
):
- # type: (StreamType, Any, Any, Any, Union[None, bool], Union[None, int], Union[None, int], Union[None, bool], Any, Any, Union[None, bool], Union[None, bool], Any, Any, Any, Any, Any) -> None # NOQA
+ # type: (StreamType, Any, Any, Any, Optional[bool], Optional[int], Optional[int], Optional[bool], Any, Any, Optional[bool], Optional[bool], Any, Any, Any, Any, Any) -> None # NOQA
CEmitter.__init__(
self,
stream,
@@ -120,7 +120,7 @@ class CSafeDumper(CEmitter, SafeRepresenter, Resolver): # type: ignore
top_level_colon_align=None,
prefix_colon=None,
):
- # type: (StreamType, Any, Any, Any, Union[None, bool], Union[None, int], Union[None, int], Union[None, bool], Any, Any, Union[None, bool], Union[None, bool], Any, Any, Any, Any, Any) -> None # NOQA
+ # type: (StreamType, Any, Any, Any, Optional[bool], Optional[int], Optional[int], Optional[bool], Any, Any, Optional[bool], Optional[bool], Any, Any, Any, Any, Any) -> None # NOQA
self._emitter = self._serializer = self._representer = self
CEmitter.__init__(
self,
@@ -163,7 +163,7 @@ class CDumper(CEmitter, Representer, Resolver): # type: ignore
top_level_colon_align=None,
prefix_colon=None,
):
- # type: (StreamType, Any, Any, Any, Union[None, bool], Union[None, int], Union[None, int], Union[None, bool], Any, Any, Union[None, bool], Union[None, bool], Any, Any, Any, Any, Any) -> None # NOQA
+ # type: (StreamType, Any, Any, Any, Optional[bool], Optional[int], Optional[int], Optional[bool], Any, Any, Optional[bool], Optional[bool], Any, Any, Any, Any, Any) -> None # NOQA
CEmitter.__init__(
self,
stream,
diff --git a/dumper.py b/dumper.py
index 5f23c45..5d99b4f 100644
--- a/dumper.py
+++ b/dumper.py
@@ -13,7 +13,7 @@ from ruamel.yaml.representer import (
from ruamel.yaml.resolver import Resolver, BaseResolver, VersionedResolver
if False: # MYPY
- from typing import Any, Dict, List, Union # NOQA
+ from typing import Any, Dict, List, Union, Optional # NOQA
from ruamel.yaml.compat import StreamType, VersionType # NOQA
__all__ = ['BaseDumper', 'SafeDumper', 'Dumper', 'RoundTripDumper']
@@ -39,7 +39,7 @@ class BaseDumper(Emitter, Serializer, BaseRepresenter, BaseResolver):
top_level_colon_align=None,
prefix_colon=None,
):
- # type: (Any, StreamType, Any, Any, Union[None, bool], Union[None, int], Union[None, int], Union[None, bool], Any, Any, Union[None, bool], Union[None, bool], Any, Any, Any, Any, Any) -> None # NOQA
+ # type: (Any, StreamType, Any, Any, Optional[bool], Optional[int], Optional[int], Optional[bool], Any, Any, Optional[bool], Optional[bool], Any, Any, Any, Any, Any) -> None # NOQA
Emitter.__init__(
self,
stream,
@@ -89,7 +89,7 @@ class SafeDumper(Emitter, Serializer, SafeRepresenter, Resolver):
top_level_colon_align=None,
prefix_colon=None,
):
- # type: (StreamType, Any, Any, Union[None, bool], Union[None, int], Union[None, int], Union[None, bool], Any, Any, Union[None, bool], Union[None, bool], Any, Any, Any, Any, Any) -> None # NOQA
+ # type: (StreamType, Any, Any, Optional[bool], Optional[int], Optional[int], Optional[bool], Any, Any, Optional[bool], Optional[bool], Any, Any, Any, Any, Any) -> None # NOQA
Emitter.__init__(
self,
stream,
@@ -139,7 +139,7 @@ class Dumper(Emitter, Serializer, Representer, Resolver):
top_level_colon_align=None,
prefix_colon=None,
):
- # type: (StreamType, Any, Any, Union[None, bool], Union[None, int], Union[None, int], Union[None, bool], Any, Any, Union[None, bool], Union[None, bool], Any, Any, Any, Any, Any) -> None # NOQA
+ # type: (StreamType, Any, Any, Optional[bool], Optional[int], Optional[int], Optional[bool], Any, Any, Optional[bool], Optional[bool], Any, Any, Any, Any, Any) -> None # NOQA
Emitter.__init__(
self,
stream,
@@ -189,7 +189,7 @@ class RoundTripDumper(Emitter, Serializer, RoundTripRepresenter, VersionedResolv
top_level_colon_align=None,
prefix_colon=None,
):
- # type: (StreamType, Any, Union[None, bool], Union[None, int], Union[None, int], Union[None, int], Union[None, bool], Any, Any, Union[None, bool], Union[None, bool], Any, Any, Any, Any, Any) -> None # NOQA
+ # type: (StreamType, Any, Optional[bool], Optional[int], Optional[int], Optional[int], Optional[bool], Any, Any, Optional[bool], Optional[bool], Any, Any, Any, Any, Any) -> None # NOQA
Emitter.__init__(
self,
stream,
diff --git a/emitter.py b/emitter.py
index e45a0b1..7a81372 100644
--- a/emitter.py
+++ b/emitter.py
@@ -20,7 +20,7 @@ from ruamel.yaml.compat import utf8, text_type, PY2, nprint, dbg, DBG_EVENT, \
# fmt: on
if False: # MYPY
- from typing import Any, Dict, List, Union, Text, Tuple # NOQA
+ from typing import Any, Dict, List, Union, Text, Tuple, Optional # NOQA
from ruamel.yaml.compat import StreamType # NOQA
__all__ = ['Emitter', 'EmitterError']
@@ -113,14 +113,14 @@ class Emitter(object):
prefix_colon=None,
dumper=None,
):
- # type: (StreamType, Any, Union[None, int], Union[None, int], Union[None, bool], Any, Union[None, int], Union[None, bool], Any, Any) -> None # NOQA
+ # type: (StreamType, Any, Optional[int], Optional[int], Optional[bool], Any, Optional[int], Optional[bool], Any, Any) -> None # NOQA
self.dumper = dumper
if self.dumper is not None and getattr(self.dumper, '_emitter', None) is None:
self.dumper._emitter = self
self.stream = stream
# Encoding can be overriden by STREAM-START.
- self.encoding = None # type: Union[None, Text]
+ self.encoding = None # type: Optional[Text]
self.allow_space_break = None
# Emitter is a state machine with a stack of states to handle nested
@@ -134,7 +134,7 @@ class Emitter(object):
# The current indentation level and the stack of previous indents.
self.indents = Indents()
- self.indent = None # type: Union[None, int]
+ self.indent = None # type: Optional[int]
# Flow level.
self.flow_level = 0
@@ -154,7 +154,7 @@ class Emitter(object):
self.column = 0
self.whitespace = True
self.indention = True
- self.no_newline = None # type: Union[None, bool] # set if directly after `- `
+ self.no_newline = None # type: Optional[bool] # set if directly after `- `
# Whether the document requires an explicit document indicator
self.open_ended = False
@@ -269,7 +269,7 @@ class Emitter(object):
return len(self.events) < count + 1
def increase_indent(self, flow=False, sequence=None, indentless=False):
- # type: (bool, Union[None, bool], bool) -> None
+ # type: (bool, Optional[bool], bool) -> None
self.indents.append(self.indent, sequence)
if self.indent is None: # top level
if flow:
diff --git a/loader.py b/loader.py
index d8cbe31..979ec62 100644
--- a/loader.py
+++ b/loader.py
@@ -16,7 +16,7 @@ from ruamel.yaml.constructor import (
from ruamel.yaml.resolver import VersionedResolver
if False: # MYPY
- from typing import Any, Dict, List, Union # NOQA
+ from typing import Any, Dict, List, Union, Optional # NOQA
from ruamel.yaml.compat import StreamTextType, VersionType # NOQA
__all__ = ['BaseLoader', 'SafeLoader', 'Loader', 'RoundTripLoader']
@@ -24,7 +24,7 @@ __all__ = ['BaseLoader', 'SafeLoader', 'Loader', 'RoundTripLoader']
class BaseLoader(Reader, Scanner, Parser, Composer, BaseConstructor, VersionedResolver):
def __init__(self, stream, version=None, preserve_quotes=None):
- # type: (StreamTextType, Union[None, VersionType], Union[None, bool]) -> None
+ # type: (StreamTextType, Optional[VersionType], Optional[bool]) -> None
Reader.__init__(self, stream, loader=self)
Scanner.__init__(self, loader=self)
Parser.__init__(self, loader=self)
@@ -35,7 +35,7 @@ class BaseLoader(Reader, Scanner, Parser, Composer, BaseConstructor, VersionedRe
class SafeLoader(Reader, Scanner, Parser, Composer, SafeConstructor, VersionedResolver):
def __init__(self, stream, version=None, preserve_quotes=None):
- # type: (StreamTextType, Union[None, VersionType], Union[None, bool]) -> None
+ # type: (StreamTextType, Optional[VersionType], Optional[bool]) -> None
Reader.__init__(self, stream, loader=self)
Scanner.__init__(self, loader=self)
Parser.__init__(self, loader=self)
@@ -46,7 +46,7 @@ class SafeLoader(Reader, Scanner, Parser, Composer, SafeConstructor, VersionedRe
class Loader(Reader, Scanner, Parser, Composer, Constructor, VersionedResolver):
def __init__(self, stream, version=None, preserve_quotes=None):
- # type: (StreamTextType, Union[None, VersionType], Union[None, bool]) -> None
+ # type: (StreamTextType, Optional[VersionType], Optional[bool]) -> None
Reader.__init__(self, stream, loader=self)
Scanner.__init__(self, loader=self)
Parser.__init__(self, loader=self)
@@ -64,7 +64,7 @@ class RoundTripLoader(
VersionedResolver,
):
def __init__(self, stream, version=None, preserve_quotes=None):
- # type: (StreamTextType, Union[None, VersionType], Union[None, bool]) -> None
+ # type: (StreamTextType, Optional[VersionType], Optional[bool]) -> None
# self.reader = Reader.__init__(self, stream)
Reader.__init__(self, stream, loader=self)
RoundTripScanner.__init__(self, loader=self)
diff --git a/main.py b/main.py
index a2a11f4..ce607bf 100644
--- a/main.py
+++ b/main.py
@@ -35,7 +35,7 @@ from ruamel.yaml.constructor import (
from ruamel.yaml.loader import Loader as UnsafeLoader
if False: # MYPY
- from typing import List, Set, Dict, Union, Any # NOQA
+ from typing import List, Set, Dict, Union, Any, Callable # NOQA
from ruamel.yaml.compat import StreamType, StreamTextType, VersionType # NOQA
if PY3:
@@ -61,7 +61,7 @@ class YAML(object):
def __init__(
self, _kw=enforce, typ=None, pure=False, output=None, plug_ins=None # input=None,
):
- # type: (Any, Any, Any, Any) -> None
+ # type: (Any, Optional[Text], Any, Any, Any) -> None
"""
_kw: not used, forces keyword arguments in 2.7 (in 3 you can do (*, safe_load=..)
typ: 'rt'/None -> RoundTripLoader/RoundTripDumper, (default)
@@ -83,7 +83,7 @@ class YAML(object):
# self._input = input
self._output = output
- self._context_manager = False
+ self._context_manager = None # type: Any
self.plug_ins = [] # type: List[Any]
for pu in ([] if plug_ins is None else plug_ins) + self.official_plug_ins():
@@ -394,7 +394,7 @@ class YAML(object):
class XLoader(self.Parser, self.Constructor, rslvr): # type: ignore
def __init__(selfx, stream, version=None, preserve_quotes=None):
- # type: (StreamTextType, Union[None, VersionType], Union[None, bool]) -> None # NOQA
+ # type: (StreamTextType, Optional[VersionType], Optional[bool]) -> None # NOQA
CParser.__init__(selfx, stream)
selfx._parser = selfx._composer = selfx
self.Constructor.__init__(selfx, loader=selfx)
@@ -411,7 +411,17 @@ class YAML(object):
if self._context_manager:
if not self._output:
raise TypeError('Missing output stream while dumping from context manager')
- self._context_manager.dump(data, transform=transform)
+ if _kw is not enforce:
+ raise TypeError(
+ '{}.dump() takes one positional argument but at least '
+ 'two were given ({!r})'.format(self.__class__.__name__, _kw)
+ )
+ if transform is not None:
+ raise TypeError(
+ '{}.dump() in the context manager cannot have transform keyword '
+ ''.format(self.__class__.__name__)
+ )
+ self._context_manager.dump(data)
else: # old style
if stream is None:
raise TypeError('Need a stream argument when not dumping from context manager')
@@ -419,6 +429,23 @@ class YAML(object):
def dump_all(self, documents, stream, _kw=enforce, transform=None):
# type: (Any, Union[Path, StreamType], Any, Any) -> Any
+ if self._context_manager:
+ raise NotImplementedError
+ if _kw is not enforce:
+ raise TypeError(
+ '{}.dump(_all) takes two positional argument but at least '
+ 'three were given ({!r})'.format(self.__class__.__name__, _kw)
+ )
+ self._output = stream
+ self._context_manager = YAMLContextManager(self, transform=transform)
+ for data in documents:
+ self._context_manager.dump(data)
+ self._context_manager.teardown_output()
+ self._output = None
+ self._context_manager = None
+
+ def Xdump_all(self, documents, stream, _kw=enforce, transform=None):
+ # type: (Any, Union[Path, StreamType], Any, Any) -> Any
"""
Serialize a sequence of Python objects into a YAML stream.
"""
@@ -515,7 +542,7 @@ class YAML(object):
top_level_colon_align=None,
prefix_colon=None,
):
- # type: (StreamType, Any, Any, Any, Union[None, bool], Union[None, int], Union[None, int], Union[None, bool], Any, Any, Union[None, bool], Union[None, bool], Any, Any, Any, Any, Any) -> None # NOQA
+ # type: (StreamType, Any, Any, Any, Optional[bool], Optional[int], Optional[int], Optional[bool], Any, Any, Optional[bool], Optional[bool], Any, Any, Any, Any, Any) -> None # NOQA
CEmitter.__init__(
selfx,
stream,
@@ -615,10 +642,12 @@ class YAML(object):
# ### context manager
def __enter__(self):
+ # type: () -> Any
self._context_manager = YAMLContextManager(self)
return self
def __exit__(self, typ, value, traceback):
+ # type: (Any, Any, Any) -> None
if typ:
print('typ', typ)
self._context_manager.teardown_output()
@@ -657,12 +686,13 @@ class YAML(object):
class YAMLContextManager(object):
- def __init__(self, yaml):
+ def __init__(self, yaml, transform=None):
+ # type: (Any, Optional[Callable]) -> None
self._yaml = yaml
self._output_inited = False
self._output_path = None
self._output = self._yaml._output
- self._transform = False
+ self._transform = transform
# self._input_inited = False
# self._input = input
@@ -673,7 +703,7 @@ class YAMLContextManager(object):
if not hasattr(self._output, 'write') and hasattr(self._output, 'open'):
# pathlib.Path() instance, open with the same mode
self._output_path = self._output
- self._output = self._output_path.open('r')
+ self._output = self._output_path.open('w')
# if not hasattr(self._stream, 'write') and hasattr(stream, 'open'):
# if not hasattr(self._input, 'read') and hasattr(self._input, 'open'):
@@ -681,14 +711,15 @@ class YAMLContextManager(object):
# self._input_path = self._input
# self._input = self._input_path.open('r')
- # if self._transform is not None:
- # self._fstream = self._stream
- # if self._yaml.encoding is None:
- # self._stream = StringIO()
- # else:
- # self._stream = BytesIO()
+ if self._transform is not None:
+ self._fstream = self._output
+ if self._yaml.encoding is None:
+ self._output = StringIO()
+ else:
+ self._output = BytesIO()
def teardown_output(self):
+ # type: () -> None
if self._output_inited:
self._yaml.serializer.close()
else:
@@ -702,21 +733,22 @@ class YAMLContextManager(object):
delattr(self._yaml, '_serializer')
delattr(self._yaml, '_emitter')
except AttributeError:
- if not typ:
- raise
+ raise
if self._transform:
- val = self._stream.getvalue() # type: ignore
+ val = self._output.getvalue()
if self._yaml.encoding:
val = val.decode(self._yaml.encoding)
if self._fstream is None:
self._transform(val)
else:
self._fstream.write(self._transform(val))
- self._fstream.close()
+ self._fstream.flush()
+ self._output = self._fstream # maybe not necessary
if self._output_path is not None:
self._output.close()
- def init_output(self, data):
+ def init_output(self, first_data):
+ # type: (Any) -> None
if self._yaml.top_level_colon_align is True:
tlca = max([len(str(x)) for x in first_data]) # type: Any
else:
@@ -725,7 +757,8 @@ class YAMLContextManager(object):
self._yaml.serializer.open()
self._output_inited = True
- def dump(self, data, transform=None):
+ def dump(self, data):
+ # type: (Any) -> None
if not self._output_inited:
self.init_output(data)
try:
@@ -853,7 +886,7 @@ def compose_all(stream, Loader=Loader):
def load(stream, Loader=None, version=None, preserve_quotes=None):
- # type: (StreamTextType, Any, Union[None, VersionType], Any) -> Any
+ # type: (StreamTextType, Any, Optional[VersionType], Any) -> Any
"""
Parse the first YAML document in a stream
and produce the corresponding Python object.
@@ -869,7 +902,7 @@ def load(stream, Loader=None, version=None, preserve_quotes=None):
def load_all(stream, Loader=None, version=None, preserve_quotes=None):
- # type: (Union[None, StreamTextType], Any, Union[None, VersionType], Union[None, bool]) -> Any # NOQA
+ # type: (Optional[StreamTextType], Any, Optional[VersionType], Optional[bool]) -> Any # NOQA
"""
Parse all YAML documents in a stream
and produce corresponding Python objects.
@@ -886,7 +919,7 @@ def load_all(stream, Loader=None, version=None, preserve_quotes=None):
def safe_load(stream, version=None):
- # type: (StreamTextType, Union[None, VersionType]) -> Any
+ # type: (StreamTextType, Optional[VersionType]) -> Any
"""
Parse the first YAML document in a stream
and produce the corresponding Python object.
@@ -896,7 +929,7 @@ def safe_load(stream, version=None):
def safe_load_all(stream, version=None):
- # type: (StreamTextType, Union[None, VersionType]) -> Any
+ # type: (StreamTextType, Optional[VersionType]) -> Any
"""
Parse all YAML documents in a stream
and produce corresponding Python objects.
@@ -906,7 +939,7 @@ def safe_load_all(stream, version=None):
def round_trip_load(stream, version=None, preserve_quotes=None):
- # type: (StreamTextType, Union[None, VersionType], Union[None, bool]) -> Any
+ # type: (StreamTextType, Optional[VersionType], Optional[bool]) -> Any
"""
Parse the first YAML document in a stream
and produce the corresponding Python object.
@@ -916,7 +949,7 @@ def round_trip_load(stream, version=None, preserve_quotes=None):
def round_trip_load_all(stream, version=None, preserve_quotes=None):
- # type: (StreamTextType, Union[None, VersionType], Union[None, bool]) -> Any
+ # type: (StreamTextType, Optional[VersionType], Optional[bool]) -> Any
"""
Parse all YAML documents in a stream
and produce corresponding Python objects.
@@ -935,7 +968,7 @@ def emit(
allow_unicode=None,
line_break=None,
):
- # type: (Any, Union[None, StreamType], Any, Union[None, bool], Union[int, None], Union[None, int], Union[None, bool], Any) -> Any # NOQA
+ # type: (Any, Optional[StreamType], Any, Optional[bool], Union[int, None], Optional[int], Optional[bool], Any) -> Any # NOQA
"""
Emit YAML parsing events into a stream.
If stream is None, return the produced string instead.
@@ -983,7 +1016,7 @@ def serialize_all(
version=None,
tags=None,
):
- # type: (Any, Union[None, StreamType], Any, Any, Union[None, int], Union[None, int], Union[None, bool], Any, Any, Union[None, bool], Union[None, bool], Union[None, VersionType], Any) -> Any # NOQA
+ # type: (Any, Optional[StreamType], Any, Any, Optional[int], Optional[int], Optional[bool], Any, Any, Optional[bool], Optional[bool], Optional[VersionType], Any) -> Any # NOQA
"""
Serialize a sequence of representation trees into a YAML stream.
If stream is None, return the produced string instead.
@@ -1024,7 +1057,7 @@ def serialize_all(
def serialize(node, stream=None, Dumper=Dumper, **kwds):
- # type: (Any, Union[None, StreamType], Any, Any) -> Any
+ # type: (Any, Optional[StreamType], Any, Any) -> Any
"""
Serialize a representation tree into a YAML stream.
If stream is None, return the produced string instead.
@@ -1052,7 +1085,7 @@ def dump_all(
top_level_colon_align=None,
prefix_colon=None,
):
- # type: (Any, Union[None, StreamType], Any, Any, Any, Union[None, bool], Union[None, int], Union[None, int], Union[None, bool], Any, Any, Union[None, bool], Union[None, bool], Any, Any, Any, Any, Any) -> Union[None, str] # NOQA
+ # type: (Any, Optional[StreamType], Any, Any, Any, Optional[bool], Optional[int], Optional[int], Optional[bool], Any, Any, Optional[bool], Optional[bool], Any, Any, Any, Any, Any) -> Optional[str] # NOQA
"""
Serialize a sequence of Python objects into a YAML stream.
If stream is None, return the produced string instead.
@@ -1122,7 +1155,7 @@ def dump(
tags=None,
block_seq_indent=None,
):
- # type: (Any, Union[None, StreamType], Any, Any, Any, Union[None, bool], Union[None, int], Union[None, int], Union[None, bool], Any, Any, Union[None, bool], Union[None, bool], Union[None, VersionType], Any, Any) -> Union[None, str] # NOQA
+ # type: (Any, Optional[StreamType], Any, Any, Any, Optional[bool], Optional[int], Optional[int], Optional[bool], Any, Any, Optional[bool], Optional[bool], Optional[VersionType], Any, Any) -> Optional[str] # NOQA
"""
Serialize a Python object into a YAML stream.
If stream is None, return the produced string instead.
@@ -1151,7 +1184,7 @@ def dump(
def safe_dump_all(documents, stream=None, **kwds):
- # type: (Any, Union[None, StreamType], Any) -> Union[None, str]
+ # type: (Any, Optional[StreamType], Any) -> Optional[str]
"""
Serialize a sequence of Python objects into a YAML stream.
Produce only basic YAML tags.
@@ -1161,7 +1194,7 @@ def safe_dump_all(documents, stream=None, **kwds):
def safe_dump(data, stream=None, **kwds):
- # type: (Any, Union[None, StreamType], Any) -> Union[None, str]
+ # type: (Any, Optional[StreamType], Any) -> Optional[str]
"""
Serialize a Python object into a YAML stream.
Produce only basic YAML tags.
@@ -1190,7 +1223,7 @@ def round_trip_dump(
top_level_colon_align=None,
prefix_colon=None,
):
- # type: (Any, Union[None, StreamType], Any, Any, Any, Union[None, bool], Union[None, int], Union[None, int], Union[None, bool], Any, Any, Union[None, bool], Union[None, bool], Union[None, VersionType], Any, Any, Any, Any) -> Union[None, str] # NOQA
+ # type: (Any, Optional[StreamType], Any, Any, Any, Optional[bool], Optional[int], Optional[int], Optional[bool], Any, Any, Optional[bool], Optional[bool], Optional[VersionType], Any, Any, Any, Any) -> Optional[str] # NOQA
allow_unicode = True if allow_unicode is None else allow_unicode
return dump_all(
[data],
diff --git a/reader.py b/reader.py
index 4d0ddb4..dc9a036 100644
--- a/reader.py
+++ b/reader.py
@@ -28,7 +28,7 @@ from ruamel.yaml.compat import text_type, binary_type, PY3, UNICODE_SIZE
from ruamel.yaml.util import RegExp
if False: # MYPY
- from typing import Any, Dict, Optional, List, Union, Text, Tuple # NOQA
+ from typing import Any, Dict, Optional, List, Union, Text, Tuple, Optional # NOQA
from ruamel.yaml.compat import StreamTextType # NOQA
__all__ = ['Reader', 'ReaderError']
@@ -93,7 +93,7 @@ class Reader(object):
self.pointer = 0
self.raw_buffer = None # type: Any
self.raw_decode = None
- self.encoding = None # type: Union[None, Text]
+ self.encoding = None # type: Optional[Text]
self.index = 0
self.line = 0
self.column = 0
@@ -202,7 +202,7 @@ class Reader(object):
@classmethod
def _get_non_printable_ascii(cls, data): # type: ignore
- # type: (Text, bytes) -> Union[None, Tuple[int, Text]]
+ # type: (Text, bytes) -> Optional[Tuple[int, Text]]
ascii_bytes = data.encode('ascii')
non_printables = ascii_bytes.translate(None, cls._printable_ascii) # type: ignore
if not non_printables:
@@ -212,7 +212,7 @@ class Reader(object):
@classmethod
def _get_non_printable_regex(cls, data):
- # type: (Text) -> Union[None, Tuple[int, Text]]
+ # type: (Text) -> Optional[Tuple[int, Text]]
match = cls.NON_PRINTABLE.search(data)
if not bool(match):
return None
@@ -220,7 +220,7 @@ class Reader(object):
@classmethod
def _get_non_printable(cls, data):
- # type: (Text) -> Union[None, Tuple[int, Text]]
+ # type: (Text) -> Optional[Tuple[int, Text]]
try:
return cls._get_non_printable_ascii(data) # type: ignore
except UnicodeEncodeError:
@@ -276,7 +276,7 @@ class Reader(object):
break
def update_raw(self, size=None):
- # type: (Union[None, int]) -> None
+ # type: (Optional[int]) -> None
if size is None:
size = 4096 if PY3 else 1024
data = self.stream.read(size)
diff --git a/representer.py b/representer.py
index 07b2535..a659977 100644
--- a/representer.py
+++ b/representer.py
@@ -26,7 +26,7 @@ else:
import copy_reg as copyreg # type: ignore
if False: # MYPY
- from typing import Dict, List, Any, Union, Text # NOQA
+ from typing import Dict, List, Any, Union, Text, Optional # NOQA
# fmt: off
__all__ = ['BaseRepresenter', 'SafeRepresenter', 'Representer',
@@ -62,7 +62,7 @@ class BaseRepresenter(object):
self.default_flow_style = default_flow_style
self.represented_objects = {} # type: Dict[Any, Any]
self.object_keeper = [] # type: List[Any]
- self.alias_key = None # type: Union[None, int]
+ self.alias_key = None # type: Optional[int]
@property
def serializer(self):
diff --git a/resolver.py b/resolver.py
index 6b8c56e..34e3d1e 100644
--- a/resolver.py
+++ b/resolver.py
@@ -5,7 +5,7 @@ from __future__ import absolute_import
import re
if False: # MYPY
- from typing import Any, Dict, List, Union, Text # NOQA
+ from typing import Any, Dict, List, Union, Text, Optional # NOQA
from ruamel.yaml.compat import VersionType # NOQA
from ruamel.yaml.compat import string_types, _DEFAULT_YAML_VERSION # NOQA
@@ -377,7 +377,7 @@ class VersionedResolver(BaseResolver):
"""
def __init__(self, version=None, loader=None):
- # type: (Union[None, VersionType], Any) -> None
+ # type: (Optional[VersionType], Any) -> None
BaseResolver.__init__(self, loader)
self._loader_version = self.get_loader_version(version)
self._version_implicit_resolver = {} # type: Dict[Any, Any]
@@ -391,7 +391,7 @@ class VersionedResolver(BaseResolver):
impl_resolver.setdefault(ch, []).append((tag, regexp))
def get_loader_version(self, version):
- # type: (Union[VersionType, None]) -> Any
+ # type: (Optional[VersionType]) -> Any
if version is None or isinstance(version, tuple):
return version
if isinstance(version, list):
diff --git a/serializer.py b/serializer.py
index b2b26bf..fa4ae62 100644
--- a/serializer.py
+++ b/serializer.py
@@ -21,7 +21,7 @@ from ruamel.yaml.events import (
from ruamel.yaml.nodes import MappingNode, ScalarNode, SequenceNode
if False: # MYPY
- from typing import Any, Dict, Union, Text # NOQA
+ from typing import Any, Dict, Union, Text, Optional # NOQA
from ruamel.yaml.compat import VersionType # NOQA
__all__ = ['Serializer', 'SerializerError']
@@ -46,7 +46,7 @@ class Serializer(object):
tags=None,
dumper=None,
):
- # type: (Any, Union[None, bool], Union[None, bool], Union[None, VersionType], Any, Any) -> None # NOQA
+ # type: (Any, Optional[bool], Optional[bool], Optional[VersionType], Any, Any) -> None # NOQA
self.dumper = dumper
if self.dumper is not None:
self.dumper._serializer = self
@@ -61,7 +61,7 @@ class Serializer(object):
self.serialized_nodes = {} # type: Dict[Any, Any]
self.anchors = {} # type: Dict[Any, Any]
self.last_anchor_id = 0
- self.closed = None # type: Union[None, bool]
+ self.closed = None # type: Optional[bool]
self._templated_id = None
@property