summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthon van der Neut <anthon@mnt.org>2017-05-29 21:57:25 +0200
committerAnthon van der Neut <anthon@mnt.org>2017-05-29 21:57:25 +0200
commit6ba66a44af41d072f5ceddfcdf2c21611c2a7cd0 (patch)
tree1d6ce2221f7e08e831b9955b23c361d6dd84b124
parent37721c337037bda3136e964b1eb5972e2587b4a0 (diff)
downloadruamel.yaml-6ba66a44af41d072f5ceddfcdf2c21611c2a7cd0.tar.gz
preserve value type, support pathlib.Path as stream
-rw-r--r--README.rst8
-rw-r--r--__init__.py4
-rw-r--r--comments.py23
-rw-r--r--emitter.py9
-rw-r--r--error.py3
-rw-r--r--reader.py9
6 files changed, 49 insertions, 7 deletions
diff --git a/README.rst b/README.rst
index b4c3c3e..e97288e 100644
--- a/README.rst
+++ b/README.rst
@@ -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):
diff --git a/emitter.py b/emitter.py
index 44dfe05..773058a 100644
--- a/emitter.py
+++ b/emitter.py
@@ -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]
diff --git a/error.py b/error.py
index 65a7a97..910e13b 100644
--- a/error.py
+++ b/error.py
@@ -126,6 +126,9 @@ class MarkedYAMLError(YAMLError):
return '\n'.join(lines)
+class YAMLStreamError(Exception):
+ pass
+
class ReusedAnchorWarning(Warning):
pass
diff --git a/reader.py b/reader.py
index 2ececae..4cc67b8 100644
--- a/reader.py
+++ b/reader.py
@@ -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