Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #110

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft

Dev #110

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion _test/lib/test_appliance.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def display(results, verbose):
sys.stdout.write('=' * 75 + '\n')
sys.stdout.write('%s(%s): %s\n' % (name, ', '.join(filenames), kind))
if kind == 'ERROR':
traceback.print_exception(file=sys.stdout, *info)
traceback.print_exception(file=sys.stdout, *info) # NOQA
else:
sys.stdout.write('Traceback (most recent call last):\n')
traceback.print_tb(info[2], file=sys.stdout)
Expand Down
97 changes: 97 additions & 0 deletions _test/test_block_seq_local_indent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import io
from typing import Any, Dict, List, Text # NOQA

import pytest

import ruyaml # NOQA
from ruyaml import YAML
from ruyaml.comments import CommentedSeq
from ruyaml.constructor import RoundTripConstructor
from ruyaml.representer import RoundTripRepresenter, ScalarNode
from ruyaml.scalarbool import ScalarBoolean
from ruyaml.util import load_yaml_guess_indent

from .roundtrip import dedent, round_trip


def round_trip_stabler(
inp,
outp=None,
):
if outp is None:
outp = inp
doutp = dedent(outp)
yaml = ruyaml.YAML()
yaml.preserve_quotes = True
yaml.preserve_block_seqs_indents = True
data = yaml.load(doutp)
buf = io.StringIO()
yaml.dump(data, stream=buf)
res = buf.getvalue()
assert res == doutp


class TestStability:
def test_blockseq1(self):
round_trip(
"""
a:
- a1
- a2
"""
)

@pytest.mark.xfail(strict=True)
def test_blockseq2(self):
round_trip(
"""
a:
- a1
- a2
"""
)

@pytest.mark.xfail(strict=True)
def test_blockseq3(self):
round_trip(
"""
a:
- a1
- a2
b:
- b1
- b2
"""
)


class TestStabilityStabler:
def test_blockseq1(self):
round_trip_stabler(
"""
a:
- a1
- a2
"""
)

def test_blockseq2(self):
round_trip_stabler(
"""
a:
- a1
- a2
"""
)

def test_blockseq3(self):
round_trip_stabler(
"""
a:
- a1
- a2
b:
- b1
- b2
"""
)
77 changes: 77 additions & 0 deletions _test/test_bools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import io
from typing import Any, Dict, List, Text # NOQA

import pytest

import ruyaml # NOQA
from ruyaml import YAML
from ruyaml.comments import CommentedSeq
from ruyaml.constructor import RoundTripConstructor
from ruyaml.representer import RoundTripRepresenter, ScalarNode
from ruyaml.scalarbool import ScalarBoolean
from ruyaml.util import load_yaml_guess_indent

from .roundtrip import dedent, round_trip


def round_trip_stabler(
inp,
outp=None,
):
if outp is None:
outp = inp
doutp = dedent(outp)
yaml = ruyaml.YAML()
yaml.preserve_quotes = True
yaml.preserve_bools = True
data = yaml.load(doutp)
buf = io.StringIO()
yaml.dump(data, stream=buf)
res = buf.getvalue()
assert res == doutp


class TestStability:
def test_lowercase_boolean(self):
round_trip(
"""
- true
"""
)

@pytest.mark.xfail(strict=True)
def test_uppercase_boolean(self):
round_trip(
"""
- True
"""
)

# @pytest.mark.xfail(strict=True) # Why not failing??
def test_yes_boolean(self):
round_trip(
"""
- yes
"""
)

def test_lowercase_boolean2(self):
round_trip_stabler(
"""
- true
"""
)

def test_uppercase_boolean2(self):
round_trip_stabler(
"""
- True
"""
)

def test_yes_boolean2(self):
round_trip_stabler(
"""
- yes
"""
)
7 changes: 4 additions & 3 deletions lib/ruyaml/constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class BaseConstructor:
yaml_constructors = {} # type: Dict[Any, Any]
yaml_multi_constructors = {} # type: Dict[Any, Any]

def __init__(self, preserve_quotes=None, loader=None):
def __init__(self, preserve_quotes=None, loader=None, preserve_bools=None):
# type: (Optional[bool], Any) -> None
self.loader = loader
if (
Expand All @@ -91,6 +91,7 @@ def __init__(self, preserve_quotes=None, loader=None):
self.state_generators = [] # type: List[Any]
self.deep_construct = False
self._preserve_quotes = preserve_quotes
self._preserve_bools = preserve_bools
self.allow_duplicate_keys = False

@property
Expand Down Expand Up @@ -1862,8 +1863,8 @@ def construct_yaml_timestamp(self, node, values=None):
def construct_yaml_bool(self, node):
# type: (Any) -> Any
b = SafeConstructor.construct_yaml_bool(self, node)
if node.anchor:
return ScalarBoolean(b, anchor=node.anchor)
if node.anchor or self._preserve_bools:
return ScalarBoolean(b, anchor=node.anchor, orig_repr=node.value)
return b


Expand Down
13 changes: 10 additions & 3 deletions lib/ruyaml/emitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,10 @@ def __init__(
top_level_colon_align=None,
prefix_colon=None,
brace_single_entry_mapping_in_flow_sequence=None,
preserve_block_seqs_indents=None,
dumper=None,
):
# type: (StreamType, Any, Optional[int], Optional[int], Optional[bool], Any, Optional[int], Optional[bool], Any, Optional[bool], Any) -> None # NOQA
# type: (StreamType, Any, Optional[int], Optional[int], Optional[bool], Any, Optional[int], Optional[bool], Any, Optional[bool], Optional[bool], Any) -> None # NOQA
self.dumper = dumper
if self.dumper is not None and getattr(self.dumper, '_emitter', None) is None:
self.dumper._emitter = self
Expand Down Expand Up @@ -185,6 +186,8 @@ def __init__(
# set to False to get "\Uxxxxxxxx" for non-basic unicode like emojis
self.unicode_supplementary = sys.maxunicode > 0xFFFF
self.sequence_dash_offset = block_seq_indent if block_seq_indent else 0
self.preserve_block_seqs_indents = preserve_block_seqs_indents
self.current_local_block_seq_indent = None
self.top_level_colon_align = top_level_colon_align
self.best_sequence_indent = 2
self.requested_indent = indent # specific for literal zero indent
Expand Down Expand Up @@ -446,6 +449,7 @@ def expect_node(self, root=False, sequence=False, mapping=False, simple_key=Fals
self.expect_scalar()
elif isinstance(self.event, SequenceStartEvent):
# nprint('@', self.indention, self.no_newline, self.column)
self.current_local_block_seq_indent = self.event.block_seq_indent
i2, n2 = self.indention, self.no_newline # NOQA
if self.event.comment:
if self.event.flow_style is False and self.event.comment:
Expand Down Expand Up @@ -669,9 +673,12 @@ def expect_block_sequence_item(self, first=False):
self.write_pre_comment(self.event)
nonl = self.no_newline if self.column == 0 else False
self.write_indent()
ind = self.sequence_dash_offset # if len(self.indents) > 1 else 0
cur_dash_offset = self.sequence_dash_offset
if self.current_local_block_seq_indent and self.preserve_block_seqs_indents:
cur_dash_offset = self.current_local_block_seq_indent
ind = cur_dash_offset # if len(self.indents) > 1 else 0
self.write_indicator(' ' * ind + '-', True, indention=True)
if nonl or self.sequence_dash_offset + 2 > self.best_sequence_indent:
if nonl or cur_dash_offset + 2 > self.best_sequence_indent:
self.no_newline = True
self.states.append(self.expect_block_sequence_item)
self.expect_node(sequence=True)
Expand Down
28 changes: 27 additions & 1 deletion lib/ruyaml/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,33 @@ def __init__(


class SequenceStartEvent(CollectionStartEvent):
__slots__ = ()
__slots__ = ('block_seq_indent',)

def __init__(
self,
anchor,
tag,
implicit,
start_mark=None,
end_mark=None,
flow_style=None,
comment=None,
block_seq_indent=None,
nr_items=None,
):
# type: (Any, Any, Any, Any, Any, Any, Any, Any, Optional[int]) -> None
CollectionStartEvent.__init__(
self,
anchor,
tag,
implicit,
start_mark,
end_mark,
flow_style,
comment,
nr_items,
)
self.block_seq_indent = block_seq_indent


class SequenceEndEvent(CollectionEndEvent):
Expand Down
9 changes: 8 additions & 1 deletion lib/ruyaml/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ def __init__(
self.prefix_colon = None
self.version = None
self.preserve_quotes = None
self.preserve_bools = None
self.preserve_block_seqs_indents = None
self.allow_duplicate_keys = False # duplicate keys in map, set
self.encoding = 'utf-8'
self.explicit_start = None
Expand Down Expand Up @@ -242,7 +244,11 @@ def constructor(self):
# type: () -> Any
attr = '_' + sys._getframe().f_code.co_name
if not hasattr(self, attr):
cnst = self.Constructor(preserve_quotes=self.preserve_quotes, loader=self)
cnst = self.Constructor(
preserve_quotes=self.preserve_quotes,
preserve_bools=self.preserve_bools,
loader=self,
)
cnst.allow_duplicate_keys = self.allow_duplicate_keys
setattr(self, attr, cnst)
return getattr(self, attr)
Expand Down Expand Up @@ -270,6 +276,7 @@ def emitter(self):
line_break=self.line_break,
prefix_colon=self.prefix_colon,
brace_single_entry_mapping_in_flow_sequence=self.brace_single_entry_mapping_in_flow_sequence, # NOQA
preserve_block_seqs_indents=self.preserve_block_seqs_indents,
dumper=self,
)
setattr(self, attr, _emitter)
Expand Down
18 changes: 17 additions & 1 deletion lib/ruyaml/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,25 @@ def __init__(


class SequenceNode(CollectionNode):
__slots__ = ()
__slots__ = ('block_seq_indent',)
id = 'sequence'

def __init__(
self,
tag,
value,
start_mark=None,
end_mark=None,
flow_style=None,
comment=None,
anchor=None,
):
# type: (Any, Any, Any, Any, Any, Any, Any) -> None
CollectionNode.__init__(
self, tag, value, start_mark, end_mark, flow_style, comment, anchor
)
self.block_seq_indent = None


class MappingNode(CollectionNode):
__slots__ = ('merge',)
Expand Down
30 changes: 23 additions & 7 deletions lib/ruyaml/representer.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,16 @@ def represent_binary(self, data):

def represent_bool(self, data, anchor=None):
# type: (Any, Optional[Any]) -> Any
try:
value = self.dumper.boolean_representation[bool(data)] # type: ignore
except AttributeError:
if data:
value = 'true'
else:
value = 'false'
if getattr(data, 'yaml_orig_repr', None) is not None:
value = data.yaml_orig_repr
else:
try:
value = self.dumper.boolean_representation[bool(data)] # type: ignore
except AttributeError:
if data:
value = 'true'
else:
value = 'false'
return self.represent_scalar('tag:yaml.org,2002:bool', value, anchor=anchor)

def represent_int(self, data):
Expand Down Expand Up @@ -812,8 +815,21 @@ def represent_sequence(self, tag, sequence, flow_style=None):
node.flow_style = self.default_flow_style
else:
node.flow_style = best_style
self.set_block_seq_indent(node, sequence)
return node

def set_block_seq_indent(self, node, sequence):
local_block_seq_indent = 10000
if not isinstance(sequence, CommentedSeq):
return
if not sequence.lc.data:
return
for lc_item in sequence.lc.data.values():
local_block_seq_indent = min(
local_block_seq_indent, lc_item[1] - 2
) # Why '2'?
node.block_seq_indent = local_block_seq_indent

def merge_comments(self, node, comments):
# type: (Any, Any) -> Any
if comments is None:
Expand Down
Loading
Loading