summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthon van der Neut <anthon@mnt.org>2018-12-27 23:37:32 +0100
committerAnthon van der Neut <anthon@mnt.org>2018-12-27 23:37:32 +0100
commit25b7008eb7721763fe0ea10cc23abeed2c1ef780 (patch)
tree6ea378f32bd05947a84bcdceedc1d90418aca13f
parentcdb3ca654eb8f6ef734b82bf9130045ce6d85e45 (diff)
downloadruamel.yaml-25b7008eb7721763fe0ea10cc23abeed2c1ef780.tar.gz
roundtrip anchors/aliases on str, int, float
-rw-r--r--__init__.py4
-rw-r--r--comments.py4
-rw-r--r--composer.py1
-rw-r--r--constructor.py43
-rw-r--r--emitter.py11
-rw-r--r--representer.py75
-rw-r--r--scalarfloat.py27
-rw-r--r--scalarint.py60
-rw-r--r--scalarstring.py51
9 files changed, 206 insertions, 70 deletions
diff --git a/__init__.py b/__init__.py
index 4300f70..c0c019a 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, 81),
- __version__='0.15.81',
+ version_info=(0, 15, 82, 'dev'),
+ __version__='0.15.82.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 7048772..5068d84 100644
--- a/comments.py
+++ b/comments.py
@@ -375,7 +375,7 @@ class CommentedBase(object):
raise NotImplementedError
-class CommentedSeq(MutableSliceableSequence, list, CommentedBase):
+class CommentedSeq(MutableSliceableSequence, list, CommentedBase): # type: ignore
__slots__ = (Comment.attrib, '_lst')
def __init__(self, *args, **kw):
@@ -508,7 +508,7 @@ class CommentedSeq(MutableSliceableSequence, list, CommentedBase):
return list.__repr__(self)
-class CommentedKeySeq(tuple, CommentedBase):
+class CommentedKeySeq(tuple, CommentedBase): # type: ignore
"""This primarily exists to be able to roundtrip keys that are sequences"""
def _yaml_add_comment(self, comment, key=NoComment):
diff --git a/composer.py b/composer.py
index 745c17a..d8d3d11 100644
--- a/composer.py
+++ b/composer.py
@@ -152,6 +152,7 @@ class Composer(object):
event.end_mark,
style=event.style,
comment=event.comment,
+ anchor=anchor,
)
if anchor is not None:
self.anchors[anchor] = node
diff --git a/constructor.py b/constructor.py
index 2d3250a..6aef100 100644
--- a/constructor.py
+++ b/constructor.py
@@ -24,7 +24,7 @@ from ruamel.yaml.comments import (CommentedMap, CommentedOrderedMap, CommentedSe
CommentedKeyMap)
from ruamel.yaml.scalarstring import (SingleQuotedScalarString, DoubleQuotedScalarString,
LiteralScalarString, FoldedScalarString,
- ScalarString,)
+ PlainScalarString, ScalarString,)
from ruamel.yaml.scalarint import ScalarInt, BinaryInt, OctalInt, HexInt, HexCapsInt
from ruamel.yaml.scalarfloat import ScalarFloat
from ruamel.yaml.timestamp import TimeStamp
@@ -1057,7 +1057,7 @@ class RoundTripConstructor(SafeConstructor):
)
if node.style == '|' and isinstance(node.value, text_type):
- lss = LiteralScalarString(node.value)
+ lss = LiteralScalarString(node.value, anchor=node.anchor)
if node.comment and node.comment[1]:
lss.comment = node.comment[1][0] # type: ignore
return lss
@@ -1069,7 +1069,7 @@ class RoundTripConstructor(SafeConstructor):
if idx < 0:
break
fold_positions.append(idx - len(fold_positions))
- fss = FoldedScalarString(node.value.replace('\a', ''))
+ fss = FoldedScalarString(node.value.replace('\a', ''), anchor=node.anchor)
if node.comment and node.comment[1]:
fss.comment = node.comment[1][0] # type: ignore
if fold_positions:
@@ -1077,9 +1077,11 @@ class RoundTripConstructor(SafeConstructor):
return fss
elif bool(self._preserve_quotes) and isinstance(node.value, text_type):
if node.style == "'":
- return SingleQuotedScalarString(node.value)
+ return SingleQuotedScalarString(node.value, anchor=node.anchor)
if node.style == '"':
- return DoubleQuotedScalarString(node.value)
+ return DoubleQuotedScalarString(node.value, anchor=node.anchor)
+ if node.anchor:
+ return PlainScalarString(node.value, anchor=node.anchor)
return node.value
def construct_yaml_int(self, node):
@@ -1108,7 +1110,10 @@ class RoundTripConstructor(SafeConstructor):
underscore[1] = value_su[2] == '_'
underscore[2] = len(value_su[2:]) > 1 and value_su[-1] == '_'
return BinaryInt( # type: ignore
- sign * int(value_s[2:], 2), width=width, underscore=underscore
+ sign * int(value_s[2:], 2),
+ width=width,
+ underscore=underscore,
+ anchor=node.anchor,
)
elif value_s.startswith('0x'):
# default to lower-case if no a-fA-F in string
@@ -1124,7 +1129,12 @@ class RoundTripConstructor(SafeConstructor):
if underscore is not None:
underscore[1] = value_su[2] == '_'
underscore[2] = len(value_su[2:]) > 1 and value_su[-1] == '_'
- return hex_fun(sign * int(value_s[2:], 16), width=width, underscore=underscore)
+ return hex_fun(
+ sign * int(value_s[2:], 16),
+ width=width,
+ underscore=underscore,
+ anchor=node.anchor,
+ )
elif value_s.startswith('0o'):
if self.resolver.processing_version > (1, 1) and value_s[2] == '0':
width = len(value_s[2:])
@@ -1132,7 +1142,10 @@ class RoundTripConstructor(SafeConstructor):
underscore[1] = value_su[2] == '_'
underscore[2] = len(value_su[2:]) > 1 and value_su[-1] == '_'
return OctalInt( # type: ignore
- sign * int(value_s[2:], 8), width=width, underscore=underscore
+ sign * int(value_s[2:], 8),
+ width=width,
+ underscore=underscore,
+ anchor=node.anchor,
)
elif self.resolver.processing_version != (1, 2) and value_s[0] == '0':
return sign * int(value_s, 8)
@@ -1157,7 +1170,11 @@ class RoundTripConstructor(SafeConstructor):
# cannot have a leading underscore
underscore[2] = len(value_su) > 1 and value_su[-1] == '_'
return ScalarInt( # type: ignore
- sign * int(value_s), width=None, underscore=underscore
+ sign * int(value_s), width=None, underscore=underscore, anchor=node.anchor
+ )
+ elif node.anchor:
+ return ScalarInt( # type: ignore
+ sign * int(value_s), width=None, anchor=node.anchor
)
else:
return sign * int(value_s)
@@ -1225,12 +1242,18 @@ class RoundTripConstructor(SafeConstructor):
exp=exp,
e_width=e_width,
e_sign=e_sign,
+ anchor=node.anchor,
)
width = len(value_so)
prec = value_so.index('.') # you can use index, this would not be float without dot
lead0 = leading_zeros(value_so)
return ScalarFloat( # type: ignore
- sign * float(value_s), width=width, prec=prec, m_sign=m_sign, m_lead0=lead0
+ sign * float(value_s),
+ width=width,
+ prec=prec,
+ m_sign=m_sign,
+ m_lead0=lead0,
+ anchor=node.anchor,
)
def construct_yaml_str(self, node):
diff --git a/emitter.py b/emitter.py
index 61ca269..7829219 100644
--- a/emitter.py
+++ b/emitter.py
@@ -402,12 +402,14 @@ class Emitter(object):
if isinstance(self.event, AliasEvent):
self.expect_alias()
elif isinstance(self.event, (ScalarEvent, CollectionStartEvent)):
- self.process_anchor(u'&')
+ if self.process_anchor(u'&') and isinstance(self.event, ScalarEvent):
+ self.no_newline = True
self.process_tag()
if isinstance(self.event, ScalarEvent):
+ # nprint('@', self.indention, self.no_newline, self.column)
self.expect_scalar()
elif isinstance(self.event, SequenceStartEvent):
- # nprintf('@', self.indention, self.no_newline, self.column)
+ # nprint('@', self.indention, self.no_newline, self.column)
i2, n2 = self.indention, self.no_newline # NOQA
if self.event.comment:
if self.event.flow_style is False and self.event.comment:
@@ -757,15 +759,16 @@ class Emitter(object):
# Anchor, Tag, and Scalar processors.
def process_anchor(self, indicator):
- # type: (Any) -> None
+ # type: (Any) -> bool
if self.event.anchor is None:
self.prepared_anchor = None
- return
+ return False
if self.prepared_anchor is None:
self.prepared_anchor = self.prepare_anchor(self.event.anchor)
if self.prepared_anchor:
self.write_indicator(indicator + self.prepared_anchor, True)
self.prepared_anchor = None
+ return True
def process_tag(self):
# type: () -> None
diff --git a/representer.py b/representer.py
index d1fd739..923b2a2 100644
--- a/representer.py
+++ b/representer.py
@@ -12,6 +12,7 @@ from ruamel.yaml.scalarstring import (
FoldedScalarString,
SingleQuotedScalarString,
DoubleQuotedScalarString,
+ PlainScalarString,
)
from ruamel.yaml.scalarint import ScalarInt, BinaryInt, OctalInt, HexInt, HexCapsInt
from ruamel.yaml.scalarfloat import ScalarFloat
@@ -147,8 +148,8 @@ class BaseRepresenter(object):
cls.yaml_multi_representers = cls.yaml_multi_representers.copy()
cls.yaml_multi_representers[data_type] = representer
- def represent_scalar(self, tag, value, style=None):
- # type: (Any, Any, Any) -> Any
+ def represent_scalar(self, tag, value, style=None, anchor=None):
+ # type: (Any, Any, Any, Any) -> Any
if style is None:
style = self.default_style
comment = None
@@ -156,7 +157,7 @@ class BaseRepresenter(object):
comment = getattr(value, 'comment', None)
if comment:
comment = [None, [comment]]
- node = ScalarNode(tag, value, style=style, comment=comment)
+ node = ScalarNode(tag, value, style=style, comment=comment, anchor=anchor)
if self.alias_key is not None:
self.represented_objects[self.alias_key] = node
return node
@@ -669,6 +670,15 @@ class RoundTripRepresenter(SafeRepresenter):
dumper=dumper,
)
+ def ignore_aliases(self, data):
+ # type: (Any) -> bool
+ try:
+ if data.anchor is not None and data.anchor.value is not None:
+ return False
+ except AttributeError:
+ pass
+ return SafeRepresenter.ignore_aliases(self, data)
+
def represent_none(self, data):
# type: (Any) -> Any
if len(self.represented_objects) == 0 and not self.serializer.use_explicit_start:
@@ -680,10 +690,11 @@ class RoundTripRepresenter(SafeRepresenter):
# type: (Any) -> Any
tag = None
style = '|'
+ anchor = data.yaml_anchor(any=True)
if PY2 and not isinstance(data, unicode):
data = unicode(data, 'ascii')
tag = u'tag:yaml.org,2002:str'
- return self.represent_scalar(tag, data, style=style)
+ return self.represent_scalar(tag, data, style=style, anchor=anchor)
represent_preserved_scalarstring = represent_literal_scalarstring
@@ -691,6 +702,7 @@ class RoundTripRepresenter(SafeRepresenter):
# type: (Any) -> Any
tag = None
style = '>'
+ anchor = data.yaml_anchor(any=True)
for fold_pos in reversed(getattr(data, 'fold_pos', [])):
if (
data[fold_pos] == ' '
@@ -701,30 +713,42 @@ class RoundTripRepresenter(SafeRepresenter):
if PY2 and not isinstance(data, unicode):
data = unicode(data, 'ascii')
tag = u'tag:yaml.org,2002:str'
- return self.represent_scalar(tag, data, style=style)
+ return self.represent_scalar(tag, data, style=style, anchor=anchor)
def represent_single_quoted_scalarstring(self, data):
# type: (Any) -> Any
tag = None
style = "'"
+ anchor = data.yaml_anchor(any=True)
if PY2 and not isinstance(data, unicode):
data = unicode(data, 'ascii')
tag = u'tag:yaml.org,2002:str'
- return self.represent_scalar(tag, data, style=style)
+ return self.represent_scalar(tag, data, style=style, anchor=anchor)
def represent_double_quoted_scalarstring(self, data):
# type: (Any) -> Any
tag = None
style = '"'
+ anchor = data.yaml_anchor(any=True)
if PY2 and not isinstance(data, unicode):
data = unicode(data, 'ascii')
tag = u'tag:yaml.org,2002:str'
- return self.represent_scalar(tag, data, style=style)
+ return self.represent_scalar(tag, data, style=style, anchor=anchor)
- def insert_underscore(self, prefix, s, underscore):
- # type: (Any, Any, Any) -> Any
+ def represent_plain_scalarstring(self, data):
+ # type: (Any) -> Any
+ tag = None
+ style = ''
+ anchor = data.yaml_anchor(any=True)
+ if PY2 and not isinstance(data, unicode):
+ data = unicode(data, 'ascii')
+ tag = u'tag:yaml.org,2002:str'
+ return self.represent_scalar(tag, data, style=style, anchor=anchor)
+
+ def insert_underscore(self, prefix, s, underscore, anchor=None):
+ # type: (Any, Any, Any, Any) -> Any
if underscore is None:
- return self.represent_scalar(u'tag:yaml.org,2002:int', prefix + s)
+ return self.represent_scalar(u'tag:yaml.org,2002:int', prefix + s, anchor=anchor)
if underscore[0]:
sl = list(s)
pos = len(s) - underscore[0]
@@ -736,7 +760,7 @@ class RoundTripRepresenter(SafeRepresenter):
s = '_' + s
if underscore[2]:
s += '_'
- return self.represent_scalar(u'tag:yaml.org,2002:int', prefix + s)
+ return self.represent_scalar(u'tag:yaml.org,2002:int', prefix + s, anchor=anchor)
def represent_scalar_int(self, data):
# type: (Any) -> Any
@@ -744,7 +768,8 @@ class RoundTripRepresenter(SafeRepresenter):
s = '{:0{}d}'.format(data, data._width)
else:
s = format(data, 'd')
- return self.insert_underscore("", s, data._underscore)
+ anchor = data.yaml_anchor(any=True)
+ return self.insert_underscore("", s, data._underscore, anchor=anchor)
def represent_binary_int(self, data):
# type: (Any) -> Any
@@ -753,7 +778,8 @@ class RoundTripRepresenter(SafeRepresenter):
s = '{:0{}b}'.format(data, data._width)
else:
s = format(data, 'b')
- return self.insert_underscore('0b', s, data._underscore)
+ anchor = data.yaml_anchor(any=True)
+ return self.insert_underscore('0b', s, data._underscore, anchor=anchor)
def represent_octal_int(self, data):
# type: (Any) -> Any
@@ -762,7 +788,8 @@ class RoundTripRepresenter(SafeRepresenter):
s = '{:0{}o}'.format(data, data._width)
else:
s = format(data, 'o')
- return self.insert_underscore('0o', s, data._underscore)
+ anchor = data.yaml_anchor(any=True)
+ return self.insert_underscore('0o', s, data._underscore, anchor=anchor)
def represent_hex_int(self, data):
# type: (Any) -> Any
@@ -771,7 +798,8 @@ class RoundTripRepresenter(SafeRepresenter):
s = '{:0{}x}'.format(data, data._width)
else:
s = format(data, 'x')
- return self.insert_underscore('0x', s, data._underscore)
+ anchor = data.yaml_anchor(any=True)
+ return self.insert_underscore('0x', s, data._underscore, anchor=anchor)
def represent_hex_caps_int(self, data):
# type: (Any) -> Any
@@ -780,12 +808,14 @@ class RoundTripRepresenter(SafeRepresenter):
s = '{:0{}X}'.format(data, data._width)
else:
s = format(data, 'X')
- return self.insert_underscore('0x', s, data._underscore)
+ anchor = data.yaml_anchor(any=True)
+ return self.insert_underscore('0x', s, data._underscore, anchor=anchor)
def represent_scalar_float(self, data):
# type: (Any) -> Any
""" this is way more complicated """
value = None
+ anchor = data.yaml_anchor(any=True)
if data != data or (data == 0.0 and data == 1.0):
value = u'.nan'
elif data == self.inf_value:
@@ -793,7 +823,7 @@ class RoundTripRepresenter(SafeRepresenter):
elif data == -self.inf_value:
value = u'-.inf'
if value:
- return self.represent_scalar(u'tag:yaml.org,2002:float', value)
+ return self.represent_scalar(u'tag:yaml.org,2002:float', value, anchor=anchor)
if data._exp is None and data._prec > 0 and data._prec == data._width - 1:
# no exponent, but trailing dot
value = u'{}{:d}.'.format(data._m_sign if data._m_sign else "", abs(int(data)))
@@ -812,7 +842,10 @@ class RoundTripRepresenter(SafeRepresenter):
else:
# exponent
m, es = u'{:{}.{}e}'.format(
- data, data._width, data._width - data._prec + (1 if data._m_sign else 0)
+ # data, data._width, data._width - data._prec + (1 if data._m_sign else 0)
+ data,
+ data._width,
+ data._width + (1 if data._m_sign else 0),
).split('e')
w = data._width if data._prec > 0 else (data._width + 1)
if data < 0:
@@ -855,7 +888,7 @@ class RoundTripRepresenter(SafeRepresenter):
if value is None:
value = to_unicode(repr(data)).lower()
- return self.represent_scalar(u'tag:yaml.org,2002:float', value)
+ return self.represent_scalar(u'tag:yaml.org,2002:float', value, anchor=anchor)
def represent_sequence(self, tag, sequence, flow_style=None):
# type: (Any, Any, Any) -> Any
@@ -1188,6 +1221,10 @@ RoundTripRepresenter.add_representer(
DoubleQuotedScalarString, RoundTripRepresenter.represent_double_quoted_scalarstring
)
+RoundTripRepresenter.add_representer(
+ PlainScalarString, RoundTripRepresenter.represent_plain_scalarstring
+)
+
RoundTripRepresenter.add_representer(ScalarInt, RoundTripRepresenter.represent_scalar_int)
RoundTripRepresenter.add_representer(BinaryInt, RoundTripRepresenter.represent_binary_int)
diff --git a/scalarfloat.py b/scalarfloat.py
index 65a1a28..0404df3 100644
--- a/scalarfloat.py
+++ b/scalarfloat.py
@@ -4,6 +4,7 @@ from __future__ import print_function, absolute_import, division, unicode_litera
import sys
from .compat import no_limit_int # NOQA
+from ruamel.yaml.anchor import Anchor
if False: # MYPY
from typing import Text, Any, Dict, List # NOQA
@@ -22,6 +23,7 @@ class ScalarFloat(float):
e_width = kw.pop('e_width', None) # type: ignore
e_sign = kw.pop('e_sign', None) # type: ignore
underscore = kw.pop('underscore', None) # type: ignore
+ anchor = kw.pop('anchor', None) # type: ignore
v = float.__new__(cls, *args, **kw) # type: ignore
v._width = width
v._prec = prec
@@ -31,6 +33,8 @@ class ScalarFloat(float):
v._e_width = e_width
v._e_sign = e_sign
v._underscore = underscore
+ if anchor is not None:
+ v.yaml_set_anchor(anchor, always_dump=True)
return v
def __iadd__(self, a): # type: ignore
@@ -74,15 +78,36 @@ class ScalarFloat(float):
x._underscore = self._underscore[:] if self._underscore is not None else None # NOQA
return x
+ @property
+ def anchor(self):
+ # type: () -> Any
+ if not hasattr(self, Anchor.attrib):
+ setattr(self, Anchor.attrib, Anchor())
+ return getattr(self, Anchor.attrib)
+
+ def yaml_anchor(self, any=False):
+ # type: (bool) -> Any
+ if not hasattr(self, Anchor.attrib):
+ return None
+ if any or self.anchor.always_dump:
+ return self.anchor
+ return None
+
+ def yaml_set_anchor(self, value, always_dump=False):
+ # type: (Any, bool) -> None
+ self.anchor.value = value
+ self.anchor.always_dump = always_dump
+
def dump(self, out=sys.stdout):
# type: (Any) -> Any
out.write(
- 'ScalarFloat({}| w:{}, p:{}, s:{}, lz:{}|{}, w:{}, s:{})\n'.format(
+ 'ScalarFloat({}| w:{}, p:{}, s:{}, lz:{}, _:{}|{}, w:{}, s:{})\n'.format(
self,
self._width, # type: ignore
self._prec, # type: ignore
self._m_sign, # type: ignore
self._m_lead0, # type: ignore
+ self._underscore, # type: ignore
self._exp, # type: ignore
self._e_width, # type: ignore
self._e_sign, # type: ignore
diff --git a/scalarint.py b/scalarint.py
index 2bd605d..6842c05 100644
--- a/scalarint.py
+++ b/scalarint.py
@@ -2,22 +2,26 @@
from __future__ import print_function, absolute_import, division, unicode_literals
+from .compat import no_limit_int # NOQA
+from ruamel.yaml.anchor import Anchor
+
if False: # MYPY
from typing import Text, Any, Dict, List # NOQA
__all__ = ['ScalarInt', 'BinaryInt', 'OctalInt', 'HexInt', 'HexCapsInt']
-from .compat import no_limit_int # NOQA
-
class ScalarInt(no_limit_int):
def __new__(cls, *args, **kw):
# type: (Any, Any, Any) -> Any
width = kw.pop('width', None) # type: ignore
underscore = kw.pop('underscore', None) # type: ignore
+ anchor = kw.pop('anchor', None) # type: ignore
v = no_limit_int.__new__(cls, *args, **kw) # type: ignore
v._width = width
v._underscore = underscore
+ if anchor is not None:
+ v.yaml_set_anchor(anchor, always_dump=True)
return v
def __iadd__(self, a): # type: ignore
@@ -65,17 +69,37 @@ class ScalarInt(no_limit_int):
) # NOQA
return x
+ @property
+ def anchor(self):
+ # type: () -> Any
+ if not hasattr(self, Anchor.attrib):
+ setattr(self, Anchor.attrib, Anchor())
+ return getattr(self, Anchor.attrib)
+
+ def yaml_anchor(self, any=False):
+ # type: (bool) -> Any
+ if not hasattr(self, Anchor.attrib):
+ return None
+ if any or self.anchor.always_dump:
+ return self.anchor
+ return None
+
+ def yaml_set_anchor(self, value, always_dump=False):
+ # type: (Any, bool) -> None
+ self.anchor.value = value
+ self.anchor.always_dump = always_dump
+
class BinaryInt(ScalarInt):
- def __new__(cls, value, width=None, underscore=None):
- # type: (Any, Any, Any) -> Any
- return ScalarInt.__new__(cls, value, width=width, underscore=underscore)
+ def __new__(cls, value, width=None, underscore=None, anchor=None):
+ # type: (Any, Any, Any, Any) -> Any
+ return ScalarInt.__new__(cls, value, width=width, underscore=underscore, anchor=anchor)
class OctalInt(ScalarInt):
- def __new__(cls, value, width=None, underscore=None):
- # type: (Any, Any, Any) -> Any
- return ScalarInt.__new__(cls, value, width=width, underscore=underscore)
+ def __new__(cls, value, width=None, underscore=None, anchor=None):
+ # type: (Any, Any, Any, Any) -> Any
+ return ScalarInt.__new__(cls, value, width=width, underscore=underscore, anchor=anchor)
# mixed casing of A-F is not supported, when loading the first non digit
@@ -85,14 +109,22 @@ class OctalInt(ScalarInt):
class HexInt(ScalarInt):
"""uses lower case (a-f)"""
- def __new__(cls, value, width=None, underscore=None):
- # type: (Any, Any, Any) -> Any
- return ScalarInt.__new__(cls, value, width=width, underscore=underscore)
+ def __new__(cls, value, width=None, underscore=None, anchor=None):
+ # type: (Any, Any, Any, Any) -> Any
+ return ScalarInt.__new__(cls, value, width=width, underscore=underscore, anchor=anchor)
class HexCapsInt(ScalarInt):
"""uses upper case (A-F)"""
- def __new__(cls, value, width=None, underscore=None):
- # type: (Any, Any, Any) -> Any
- return ScalarInt.__new__(cls, value, width=width, underscore=underscore)
+ def __new__(cls, value, width=None, underscore=None, anchor=None):
+ # type: (Any, Any, Any, Any) -> Any
+ return ScalarInt.__new__(cls, value, width=width, underscore=underscore, anchor=anchor)
+
+
+class DecimalInt(ScalarInt):
+ """needed if anchor"""
+
+ def __new__(cls, value, width=None, underscore=None, anchor=None):
+ # type: (Any, Any, Any, Any) -> Any
+ return ScalarInt.__new__(cls, value, width=width, underscore=underscore, anchor=anchor)
diff --git a/scalarstring.py b/scalarstring.py
index 0566164..bf3cbab 100644
--- a/scalarstring.py
+++ b/scalarstring.py
@@ -14,6 +14,7 @@ __all__ = [
'FoldedScalarString',
'SingleQuotedScalarString',
'DoubleQuotedScalarString',
+ 'PlainScalarString',
# PreservedScalarString is the old name, as it was the first to be preserved on rt,
# use LiteralScalarString instead
'PreservedScalarString',
@@ -25,7 +26,11 @@ class ScalarString(text_type):
def __new__(cls, *args, **kw):
# type: (Any, Any) -> Any
- return text_type.__new__(cls, *args, **kw) # type: ignore
+ anchor = kw.pop('anchor', None) # type: ignore
+ ret_val = text_type.__new__(cls, *args, **kw) # type: ignore
+ if anchor is not None:
+ ret_val.yaml_set_anchor(anchor, always_dump=True)
+ return ret_val
def replace(self, old, new, maxreplace=-1):
# type: (Any, Any, int) -> Any
@@ -38,13 +43,13 @@ class ScalarString(text_type):
setattr(self, Anchor.attrib, Anchor())
return getattr(self, Anchor.attrib)
- def yaml_anchor(self):
- # type: () -> Any
+ def yaml_anchor(self, any=False):
+ # type: (bool) -> Any
if not hasattr(self, Anchor.attrib):
return None
- if not self.anchor.always_dump:
- return None
- return self.anchor
+ if any or self.anchor.always_dump:
+ return self.anchor
+ return None
def yaml_set_anchor(self, value, always_dump=False):
# type: (Any, bool) -> None
@@ -57,9 +62,9 @@ class LiteralScalarString(ScalarString):
style = '|'
- def __new__(cls, value):
- # type: (Text) -> Any
- return ScalarString.__new__(cls, value)
+ def __new__(cls, value, anchor=None):
+ # type: (Text, Any) -> Any
+ return ScalarString.__new__(cls, value, anchor=anchor)
PreservedScalarString = LiteralScalarString
@@ -70,9 +75,9 @@ class FoldedScalarString(ScalarString):
style = '>'
- def __new__(cls, value):
- # type: (Text) -> Any
- return ScalarString.__new__(cls, value)
+ def __new__(cls, value, anchor=None):
+ # type: (Text, Any) -> Any
+ return ScalarString.__new__(cls, value, anchor=anchor)
class SingleQuotedScalarString(ScalarString):
@@ -80,9 +85,9 @@ class SingleQuotedScalarString(ScalarString):
style = "'"
- def __new__(cls, value):
- # type: (Text) -> Any
- return ScalarString.__new__(cls, value)
+ def __new__(cls, value, anchor=None):
+ # type: (Text, Any) -> Any
+ return ScalarString.__new__(cls, value, anchor=anchor)
class DoubleQuotedScalarString(ScalarString):
@@ -90,9 +95,19 @@ class DoubleQuotedScalarString(ScalarString):
style = '"'
- def __new__(cls, value):
- # type: (Text) -> Any
- return ScalarString.__new__(cls, value)
+ def __new__(cls, value, anchor=None):
+ # type: (Text, Any) -> Any
+ return ScalarString.__new__(cls, value, anchor=anchor)
+
+
+class PlainScalarString(ScalarString):
+ __slots__ = ()
+
+ style = ''
+
+ def __new__(cls, value, anchor=None):
+ # type: (Text, Any) -> Any
+ return ScalarString.__new__(cls, value, anchor=anchor)
def preserve_literal(s):