diff options
author | Anthon van der Neut <anthon@mnt.org> | 2017-05-29 21:57:25 +0200 |
---|---|---|
committer | Anthon van der Neut <anthon@mnt.org> | 2017-05-29 21:57:25 +0200 |
commit | 6ba66a44af41d072f5ceddfcdf2c21611c2a7cd0 (patch) | |
tree | 1d6ce2221f7e08e831b9955b23c361d6dd84b124 | |
parent | 37721c337037bda3136e964b1eb5972e2587b4a0 (diff) | |
download | ruamel.yaml-6ba66a44af41d072f5ceddfcdf2c21611c2a7cd0.tar.gz |
preserve value type, support pathlib.Path as stream
-rw-r--r-- | README.rst | 8 | ||||
-rw-r--r-- | __init__.py | 4 | ||||
-rw-r--r-- | comments.py | 23 | ||||
-rw-r--r-- | emitter.py | 9 | ||||
-rw-r--r-- | error.py | 3 | ||||
-rw-r--r-- | reader.py | 9 |
6 files changed, 49 insertions, 7 deletions
@@ -18,6 +18,14 @@ ChangeLog .. should insert NEXT: at the beginning of line for next key +NEXT: + - it is no allowed to pass in a ``pathlib.Path`` as "stream" parameter to all + load/dump functions + - passing in a non-supported object (e.g. a string) as "stream" will result in a + much more meaningful YAMLStreamError. + - assigning a normal string value to an existing CommentedMap key or CommentedSeq + element will result in a value cast to the previous value's type if possible. + 0.14.12 (2017-05-14): - fix for issue 119, deepcopy not returning subclasses (reported and PR by Constantine Evans <cevans@evanslabs.org>) diff --git a/__init__.py b/__init__.py index 64e093c..e33f19e 100644 --- a/__init__.py +++ b/__init__.py @@ -11,8 +11,8 @@ if False: # MYPY _package_data = dict( full_package_name='ruamel.yaml', - version_info=(0, 14, 12), - __version__='0.14.12', + version_info=(0, 14, 13, 'dev'), + __version__='0.14.13.dev', 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/comments.py b/comments.py index 6bee2ac..93974d9 100644 --- a/comments.py +++ b/comments.py @@ -12,7 +12,8 @@ import copy from collections import MutableSet, Sized, Set -from ruamel.yaml.compat import ordereddict, PY2 +from ruamel.yaml.compat import ordereddict, PY2, string_types +from ruamel.yaml.scalarstring import ScalarString if False: # MYPY from typing import Any, Dict, Optional, List, Union # NOQA @@ -435,6 +436,16 @@ class CommentedSeq(list, CommentedBase): self.copy_attributes(res, deep=True) return res + def __setitem__(self, idx, value): + # type: (Any, Any) -> None + # try to preserve the scalarstring type if setting an existing key to a new value + if idx < len(self): + if isinstance(value, string_types) and \ + not isinstance(value, ScalarString) and \ + isinstance(self[idx], ScalarString): + value = type(self[idx])(value) + list.__setitem__(self, idx, value) + class CommentedKeySeq(tuple, CommentedBase): """This primarily exists to be able to roundtrip keys that are sequences""" @@ -684,6 +695,16 @@ class CommentedMap(ordereddict, CommentedBase): return merged[1][key] raise + def __setitem__(self, key, value): + # type: (Any, Any) -> None + # try to preserve the scalarstring type if setting an existing key to a new value + if key in self: + if isinstance(value, string_types) and \ + not isinstance(value, ScalarString) and \ + isinstance(self[key], ScalarString): + value = type(self[key])(value) + ordereddict.__setitem__(self, key, value) + def _unmerged_contains(self, key): # type: (Any) -> Any if ordereddict.__contains__(self, key): @@ -10,7 +10,7 @@ from __future__ import print_function # sequence ::= SEQUENCE-START node* SEQUENCE-END # mapping ::= MAPPING-START (node node)* MAPPING-END -from ruamel.yaml.error import YAMLError +from ruamel.yaml.error import YAMLError, YAMLStreamError from ruamel.yaml.events import * # NOQA from ruamel.yaml.compat import utf8, text_type, PY2, nprint, dbg, DBG_EVENT, \ check_anchorname_char @@ -58,7 +58,12 @@ class Emitter(object): if self.dumper is not None: self.dumper._emitter = self # The stream should have the methods `write` and possibly `flush`. - self.stream = stream + if not hasattr(stream, 'write') and hasattr(stream, 'open'): + self.stream = stream.open('w') # pathlib.Path() instance + else: + if not hasattr(stream, 'write'): + raise YAMLStreamError('stream argument needs to have a write() method') + self.stream = stream # Encoding can be overriden by STREAM-START. self.encoding = None # type: Union[None, Text] @@ -126,6 +126,9 @@ class MarkedYAMLError(YAMLError): return '\n'.join(lines) +class YAMLStreamError(Exception): + pass + class ReusedAnchorWarning(Warning): pass @@ -23,7 +23,7 @@ from __future__ import absolute_import import codecs import re -from ruamel.yaml.error import YAMLError, FileMark, StringMark +from ruamel.yaml.error import YAMLError, FileMark, StringMark, YAMLStreamError from ruamel.yaml.compat import text_type, binary_type, PY3 if False: # MYPY @@ -97,7 +97,12 @@ class Reader(object): self.raw_buffer = stream self.determine_encoding() else: - self.stream = stream + if not hasattr(stream, 'read') and hasattr(stream, 'open'): + self.stream = stream.open('r') + else: + if not hasattr(stream, 'read'): + raise YAMLStreamError('stream argument needs to have a read() method') + self.stream = stream self.name = getattr(stream, 'name', "<file>") self.eof = False self.raw_buffer = None |