diff options
author | Anthon van der Neut <anthon@mnt.org> | 2017-06-23 10:00:48 +0200 |
---|---|---|
committer | Anthon van der Neut <anthon@mnt.org> | 2017-06-23 10:00:48 +0200 |
commit | d6c70cf83ffb69e2ced6f909181d7bafc7b4aa8b (patch) | |
tree | 16cff06beab06383fb3ab11ba68060a227ac9d10 | |
parent | 48c71076ddeab61622d8ae206ffe927553d6270a (diff) | |
download | ruamel.yaml-d6c70cf83ffb69e2ced6f909181d7bafc7b4aa8b.tar.gz |
level zero literals, renamed plug-in, mypy updates
-rw-r--r-- | .hgignore | 24 | ||||
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | README.rst | 68 | ||||
-rw-r--r-- | __init__.py | 11 | ||||
-rw-r--r-- | _test/roundtrip.py | 15 | ||||
-rw-r--r-- | _test/test_literal.py | 96 | ||||
-rw-r--r-- | emitter.py | 20 | ||||
-rw-r--r-- | main.py | 17 | ||||
-rw-r--r-- | parser.py | 1 | ||||
-rw-r--r-- | scanner.py | 2 | ||||
-rw-r--r-- | setup.py | 50 | ||||
-rw-r--r-- | tox.ini | 2 |
13 files changed, 194 insertions, 127 deletions
@@ -1,29 +1,11 @@ syntax: glob -# python derivatives -*.pyc -*.pyo -*$py.class -# backup files -*~ -*.bak -*.o -*.orig -.ruamel -# pip / setup related -dist -build -*.egg-info -# tox related -.tox -.cache +MAKEFILE -_yaml.so +# _yaml.so README.pdf venv -convert -cmd TODO.rst _doc/_build -.dcw_alt.yml +_bg_info try_* @@ -1,3 +1,8 @@ +[0, 15, 10]: 2017-06-23 + - top level PreservedScalarString not indented if not explicitly asked to + - remove Makefile (not very useful anyway) + - some mypy additions + [0, 15, 9]: 2017-06-16 - fix for issue 127: tagged scalars were always quoted and seperated by a newline when in a block sequence (reported and largely fixed by diff --git a/Makefile b/Makefile deleted file mode 100644 index af74053..0000000 --- a/Makefile +++ /dev/null @@ -1,10 +0,0 @@ - -UTILNAME:=yaml -PKGNAME:=ruamel.yaml -INSTPKGNAME:=--pkg ruamel.yaml -VERSION:=0.15.9.dev -VERSIOND:=0.15.9.dev0 - -include ~/.config/develop/Makefile.inc - -clean: clean_common @@ -32,6 +32,11 @@ ChangeLog .. should insert NEXT: at the beginning of line for next key +0.15.10 (2017-06-23): + - top level PreservedScalarString not indented if not explicitly asked to + - remove Makefile (not very useful anyway) + - some mypy additions + 0.15.9 (2017-06-16): - fix for issue 127: tagged scalars were always quoted and seperated by a newline when in a block sequence (reported and largely fixed by @@ -140,69 +145,6 @@ ChangeLog deprecated soon - some extra tests on main.py functions -0.13.14 (2017-02-12): - - fix for issue 97: clipped block scalar followed by empty lines and comment - would result in two CommentTokens of which the first was dropped. - (reported by Colm O'Connor) - -0.13.13 (2017-01-28): - - fix for issue 96: prevent insertion of extra empty line if indented mapping entries - are separated by an empty line (reported by Derrick Sawyer) - -0.13.11 (2017-01-23): - - allow ':' in flow style scalars if not followed by space. Also don't - quote such scalar as this is no longer necessary. - - add python 3.6 manylinux wheel to PyPI - -0.13.10 (2017-01-22): - - fix for issue 93, insert spurious blank line before single line comment - between indented sequence elements (reported by Alex) - -0.13.9 (2017-01-18): - - fix for issue 92, wrong import name reported by the-corinthian - -0.13.8 (2017-01-18): - - fix for issue 91, when a compiler is unavailable reported by Maximilian Hils - - fix for deepcopy issue with TimeStamps not preserving 'T', reported on - `StackOverflow Q&A <http://stackoverflow.com/a/41577841/1307905>`_ by - `Quuxplusone <http://stackoverflow.com/users/1424877/quuxplusone>`_ - - -0.13.7 (2016-12-27): - - fix for issue 85, constructor.py importing unicode_literals caused mypy to fail - on 2.7 (reported by Peter Amstutz) - -0.13.6 (2016-12-27): - - fix for issue 83, collections.OrderedDict not representable by SafeRepresenter - (reported by Frazer McLean) - -0.13.5 (2016-12-25): - - fix for issue 84, deepcopy not properly working (reported by Peter Amstutz) - -0.13.4 (2016-12-05): - - another fix for issue 82, change to non-global resolver data broke implicit type - specification - -0.13.3 (2016-12-05): - - fix for issue 82, deepcopy not working (reported by code monk) - -0.13.2 (2016-11-28): - - fix for comments after empty (null) values (reported by dsw2127 and cokelaer) - -0.13.1 (2016-11-22): - - optimisations on memory usage when loading YAML from large files (py3: -50%, py2: -85%) - -0.13.0 (2016-11-20): - - if ``load()`` or ``load_all()`` is called with only a single argument - (stream or string) - a UnsafeLoaderWarning will be issued once. If appropriate you can surpress this - warning by filtering it. Explicitly supplying the ``Loader=ruamel.yaml.Loader`` - argument, will also prevent it from being issued. You should however consider - using ``safe_load()``, ``safe_load_all()`` if your YAML input does not use tags. - - allow adding comments before and after keys (based on - `StackOveflow Q&A <http://stackoverflow.com/a/40705671/1307905>`_ by - `msinn <http://stackoverflow.com/users/7185467/msinn>`_) - ---- For older changes see the file diff --git a/__init__.py b/__init__.py index 38b8257..ee4a146 100644 --- a/__init__.py +++ b/__init__.py @@ -2,17 +2,13 @@ from __future__ import print_function, absolute_import, division, unicode_literals -# install_requires of ruamel.base is not really required but the old -# ruamel.base installed __init__.py, and thus a new version should -# be installed at some point - if False: # MYPY from typing import Dict, Any # NOQA _package_data = dict( full_package_name='ruamel.yaml', - version_info=(0, 15, 9), - __version__='0.15.9', + version_info=(0, 15, 10), + __version__='0.15.10', 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 @@ -20,7 +16,7 @@ _package_data = dict( since=2014, extras_require={':platform_python_implementation=="CPython" and python_version<="2.7"': [ 'ruamel.ordereddict', - ], 'jinja2': ['ruamel.yaml.jinja2']}, + ], 'jinja2': ['ruamel.yaml.jinja2>=0.2']}, ext_modules=[dict( name='_ruamel_yaml', src=['ext/_ruamel_yaml.c', 'ext/api.c', 'ext/writer.c', 'ext/dumper.c', @@ -57,6 +53,7 @@ _package_data = dict( ), ) # type: Dict[Any, Any] + version_info = _package_data['version_info'] __version__ = _package_data['__version__'] diff --git a/_test/roundtrip.py b/_test/roundtrip.py index 7540bcd..ac41e7b 100644 --- a/_test/roundtrip.py +++ b/_test/roundtrip.py @@ -7,6 +7,7 @@ helper routines for testing round trip of commented YAML data import textwrap import ruamel.yaml +from ruamel.yaml.compat import StringIO, BytesIO # NOQA def dedent(data): @@ -100,3 +101,17 @@ class YAML(ruamel.yaml.YAML): stream = stream[1:] stream = textwrap.dedent(stream) return ruamel.yaml.YAML.load(self, stream) + + def dump(self, data, **kw): + assert ('stream' in kw) ^ ('compare' in kw) + if 'stream' in kw: + return ruamel.yaml.YAML.dump(data, **kw) + lkw = kw.copy() + expected = textwrap.dedent(lkw.pop('compare')) + if expected and expected[0] == '\n': + expected = expected[1:] + lkw['stream'] = st = StringIO() if self.encoding is None else BytesIO() + ruamel.yaml.YAML.dump(self, data, **lkw) + res = st.getvalue() + print(res) + assert res == expected diff --git a/_test/test_literal.py b/_test/test_literal.py index 60bc143..6068b3a 100644 --- a/_test/test_literal.py +++ b/_test/test_literal.py @@ -153,3 +153,99 @@ class TestNoIndent: """.format(s)) print(d) assert d == s + '\n' + + +class Test_RoundTripLiteral: + def test_rt_top_literal_scalar_no_indent(self): + yaml = YAML() + yaml.explicit_start = True + s = 'testing123' + ys = """ + --- | + {} + """.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_rt_top_literal_scalar_indent(self): + yaml = YAML() + yaml.explicit_start = True + yaml.indent = 4 + s = 'testing123' + ys = """ + --- | + {} + """.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_rt_top_plain_scalar_no_indent(self): + yaml = YAML() + yaml.explicit_start = True + yaml.indent = 0 + s = 'testing123' + ys = """ + --- + {} + """.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_rt_top_plain_scalar_expl_indent(self): + yaml = YAML() + yaml.explicit_start = True + yaml.indent = 4 + s = 'testing123' + ys = """ + --- + {} + """.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_rt_top_sq_scalar_expl_indent(self): + yaml = YAML() + yaml.explicit_start = True + yaml.indent = 4 + s = "'testing: 123'" + ys = """ + --- + {} + """.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_rt_top_dq_scalar_expl_indent(self): + # if yaml.indent is the default (None) + # then write after the directive indicator + yaml = YAML() + yaml.explicit_start = True + yaml.indent = 0 + s = '"\'testing123"' + ys = """ + --- + {} + """.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_rt_top_literal_scalar_no_indent_no_eol(self): + yaml = YAML() + yaml.explicit_start = True + s = 'testing123' + ys = """ + --- |- + {} + """.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_rt_non_top_literal_scalar(self): + yaml = YAML() + s = 'testing123' + ys = """ + - | + {} + """.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) @@ -109,6 +109,7 @@ class Emitter(object): self.block_seq_indent = block_seq_indent if block_seq_indent else 0 self.top_level_colon_align = top_level_colon_align self.best_indent = 2 + self.requested_indent = indent # specific for literal zero indent if indent and 1 < indent < 10: self.best_indent = indent # if self.best_indent < self.block_seq_indent + 1: @@ -1027,6 +1028,11 @@ class Emitter(object): def write_single_quoted(self, text, split=True): # type: (Any, Any) -> None + if self.root_context: + if self.requested_indent is not None: + self.write_line_break() + if self.requested_indent != 0: + self.write_indent() self.write_indicator(u'\'', True) spaces = False breaks = False @@ -1100,6 +1106,11 @@ class Emitter(object): def write_double_quoted(self, text, split=True): # type: (Any, Any) -> None + if self.root_context: + if self.requested_indent is not None: + self.write_line_break() + if self.requested_indent != 0: + self.write_indent() self.write_indicator(u'"', True) start = end = 0 while end <= len(text): @@ -1239,7 +1250,7 @@ class Emitter(object): self.write_line_break() else: self.write_line_break(br) - if ch is not None: + if ch is not None and (not self.root_context or self.requested_indent): self.write_indent() start = end else: @@ -1258,7 +1269,12 @@ class Emitter(object): def write_plain(self, text, split=True): # type: (Any, Any) -> None if self.root_context: - self.open_ended = True + if self.requested_indent is not None: + self.write_line_break() + if self.requested_indent != 0: + self.write_indent() + else: + self.open_ended = True if not text: return if not self.whitespace: @@ -45,7 +45,7 @@ enforce = object() class YAML(object): def __init__(self, _kw=enforce, typ=None, pure=False, plug_ins=None): - # type: (Any, Any, Any) -> None + # type: (Any, 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) @@ -60,7 +60,7 @@ class YAML(object): "one was given ({!r})".format(self.__class__.__name__, _kw)) self.typ = 'rt' if typ is None else typ - self.plug_ins = [] + self.plug_ins = [] # type: List[Any] for pu in ([] if plug_ins is None else plug_ins) + self.official_plug_ins(): file_name = pu.replace('/', '.') self.plug_ins.append(import_module(file_name)) @@ -252,11 +252,11 @@ class YAML(object): finally: parser.dispose() try: - self._reader.reset_reader() + self._reader.reset_reader() # type: ignore except AttributeError: pass try: - self._scanner.reset_scanner() + self._scanner.reset_scanner() # type: ignore except AttributeError: pass @@ -280,11 +280,11 @@ class YAML(object): finally: parser.dispose() try: - self._reader.reset_reader() + self._reader.reset_reader() # type: ignore except AttributeError: pass try: - self._scanner.reset_scanner() + self._scanner.reset_scanner() # type: ignore except AttributeError: pass @@ -380,7 +380,7 @@ class YAML(object): delattr(self, "_serializer") delattr(self, "_emitter") if transform: - fstream.write(transform(stream.getvalue())) + fstream.write(transform(stream.getvalue())) # type: ignore return None def get_serializer_representer_emitter(self, stream, tlca): @@ -446,9 +446,10 @@ class YAML(object): # helpers def official_plug_ins(self): + # type: () -> Any bd = os.path.dirname(__file__) gpbd = os.path.dirname(os.path.dirname(bd)) - res = [x.replace(gpbd, '')[1:-3] for x in glob.glob(bd + '/*/yaml_plugin.py')] + res = [x.replace(gpbd, '')[1:-3] for x in glob.glob(bd + '/*/__plug_in__.py')] return res @@ -119,6 +119,7 @@ class Parser(object): self.state = self.parse_stream_start # type: Any def dispose(self): + # type: () -> None self.reset_parser() @property @@ -143,7 +143,7 @@ class Scanner(object): # type: () -> VersionType if hasattr(self.loader, 'typ'): return self.loader.resolver.processing_version # type: ignore - return self.loader.processing_version + return self.loader.processing_version # type: ignore # Public methods. @@ -15,6 +15,8 @@ from ast import parse # NOQA from setuptools import setup, Extension, Distribution # NOQA from setuptools.command import install_lib # NOQA +from setuptools.command.sdist import sdist as _sdist # NOQA +from wheel.bdist_wheel import bdist_wheel as _bdist_wheel # NOQA if __name__ != '__main__': raise NotImplementedError('should never include setup.py') @@ -231,6 +233,28 @@ class MyInstallLib(install_lib.install_lib): return alt_files +class MySdist(_sdist): + def initialize_options(self): + _sdist.initialize_options(self) + # because of unicode_literals + self.formats = [b'bztar'] if sys.version_info < (3, ) else ['bztar'] + dist_base = os.environ.get('PYDISTBASE') + fpn = getattr(getattr(self, 'nsp', self), 'full_package_name', None) + if fpn and dist_base: + print('setting distdir {}/{}'.format(dist_base, fpn)) + self.dist_dir = os.path.join(dist_base, fpn) + + +class MyBdistWheel(_bdist_wheel): + def initialize_options(self): + _bdist_wheel.initialize_options(self) + dist_base = os.environ.get('PYDISTBASE') + fpn = getattr(getattr(self, 'nsp', self), 'full_package_name', None) + if fpn and dist_base: + print('setting distdir {}/{}'.format(dist_base, fpn)) + self.dist_dir = os.path.join(dist_base, fpn) + + class InMemoryZipFile(object): def __init__(self, file_name=None): try: @@ -359,16 +383,6 @@ class NameSpacePackager(object): if pd.get('nested', False): continue self._split.append(self.full_package_name + '.' + d) - # x = os.path.join(d, 'setup.py') - # if os.path.exists(x): - # if not os.path.exists(os.path.join(d, 'tox.ini')): - # print('\n>>>>> found "{0}" without tox.ini <<<<<\n' - # ''.format(x)) - # # raise NotImplementedError('XXXX') - # continue - # x = os.path.join(d, '__init__.py') - # if os.path.exists(x): - # self._split.append(self.full_package_name + '.' + d) if sys.version_info < (3, ): self._split = [(y.encode('utf-8') if isinstance(y, unicode) else y) for y in self._split] @@ -805,12 +819,16 @@ def main(): if dump_kw in sys.argv: import wheel import distutils - print('python: ', sys.version) - print('distutils:', distutils.__version__) - print('wheel: ', wheel.__version__) + import setuptools + print('python: ', sys.version) + print('setuptools:', setuptools.__version__) + print('distutils: ', distutils.__version__) + print('wheel: ', wheel.__version__) nsp = NameSpacePackager(pkg_data) nsp.check() nsp.create_dirs() + MySdist.nsp = nsp + MyBdistWheel.nsp = nsp kw = dict( name=nsp.full_package_name, namespace_packages=nsp.namespace_packages, @@ -819,7 +837,11 @@ def main(): url=nsp.url, author=nsp.author, author_email=nsp.author_email, - cmdclass={'install_lib': MyInstallLib}, + cmdclass=dict( + install_lib=MyInstallLib, + sdist=MySdist, + bdist_wheel=MyBdistWheel, + ), package_dir=nsp.package_dir, entry_points=nsp.entry_points(), description=nsp.description, @@ -11,7 +11,7 @@ deps = [testenv:pep8] commands = - flake8 {posargs} + flake8 --exclude jabsy,jinja2,base,cmd,convert{posargs} [flake8] show-source = True |