Skip to content

Commit 91aeca4

Browse files
author
guibog
committed
Add preserve_block_seqs_indents
1 parent 05d641b commit 91aeca4

File tree

7 files changed

+155
-5
lines changed

7 files changed

+155
-5
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
2+
import pytest
3+
import io
4+
import ruyaml # NOQA
5+
from .roundtrip import round_trip, dedent
6+
7+
from ruyaml import YAML
8+
from ruyaml.util import load_yaml_guess_indent
9+
from ruyaml.scalarbool import ScalarBoolean
10+
from ruyaml.comments import CommentedSeq
11+
from ruyaml.representer import RoundTripRepresenter, ScalarNode
12+
from ruyaml.constructor import RoundTripConstructor
13+
from typing import Text, Any, Dict, List # NOQA
14+
15+
16+
def round_trip_stabler(
17+
inp,
18+
outp=None,
19+
):
20+
if outp is None:
21+
outp = inp
22+
doutp = dedent(outp)
23+
yaml = ruyaml.YAML()
24+
yaml.preserve_quotes = True
25+
yaml.preserve_block_seqs_indents = True
26+
data = yaml.load(doutp)
27+
buf = io.StringIO()
28+
yaml.dump(data, stream=buf)
29+
res = buf.getvalue()
30+
assert res == doutp
31+
32+
33+
class TestStability:
34+
35+
def test_blockseq1(self):
36+
round_trip(
37+
"""
38+
a:
39+
- a1
40+
- a2
41+
"""
42+
)
43+
44+
@pytest.mark.xfail(strict=True)
45+
def test_blockseq2(self):
46+
round_trip(
47+
"""
48+
a:
49+
- a1
50+
- a2
51+
"""
52+
)
53+
54+
@pytest.mark.xfail(strict=True)
55+
def test_blockseq3(self):
56+
round_trip(
57+
"""
58+
a:
59+
- a1
60+
- a2
61+
b:
62+
- b1
63+
- b2
64+
"""
65+
)
66+
67+
class TestStabilityStabler:
68+
69+
def test_blockseq1(self):
70+
round_trip_stabler(
71+
"""
72+
a:
73+
- a1
74+
- a2
75+
"""
76+
)
77+
78+
def test_blockseq2(self):
79+
round_trip_stabler(
80+
"""
81+
a:
82+
- a1
83+
- a2
84+
"""
85+
)
86+
87+
def test_blockseq3(self):
88+
round_trip_stabler(
89+
"""
90+
a:
91+
- a1
92+
- a2
93+
b:
94+
- b1
95+
- b2
96+
"""
97+
)

lib/ruyaml/emitter.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,10 @@ def __init__(
117117
top_level_colon_align=None,
118118
prefix_colon=None,
119119
brace_single_entry_mapping_in_flow_sequence=None,
120+
preserve_block_seqs_indents=None,
120121
dumper=None,
121122
):
122-
# type: (StreamType, Any, Optional[int], Optional[int], Optional[bool], Any, Optional[int], Optional[bool], Any, Optional[bool], Any) -> None # NOQA
123+
# type: (StreamType, Any, Optional[int], Optional[int], Optional[bool], Any, Optional[int], Optional[bool], Any, Optional[bool], Optional[bool], Any) -> None # NOQA
123124
self.dumper = dumper
124125
if self.dumper is not None and getattr(self.dumper, '_emitter', None) is None:
125126
self.dumper._emitter = self
@@ -185,6 +186,8 @@ def __init__(
185186
# set to False to get "\Uxxxxxxxx" for non-basic unicode like emojis
186187
self.unicode_supplementary = sys.maxunicode > 0xFFFF
187188
self.sequence_dash_offset = block_seq_indent if block_seq_indent else 0
189+
self.preserve_block_seqs_indents = preserve_block_seqs_indents
190+
self.current_local_block_seq_indent = None
188191
self.top_level_colon_align = top_level_colon_align
189192
self.best_sequence_indent = 2
190193
self.requested_indent = indent # specific for literal zero indent
@@ -446,6 +449,7 @@ def expect_node(self, root=False, sequence=False, mapping=False, simple_key=Fals
446449
self.expect_scalar()
447450
elif isinstance(self.event, SequenceStartEvent):
448451
# nprint('@', self.indention, self.no_newline, self.column)
452+
self.current_local_block_seq_indent = self.event.block_seq_indent
449453
i2, n2 = self.indention, self.no_newline # NOQA
450454
if self.event.comment:
451455
if self.event.flow_style is False and self.event.comment:
@@ -669,9 +673,12 @@ def expect_block_sequence_item(self, first=False):
669673
self.write_pre_comment(self.event)
670674
nonl = self.no_newline if self.column == 0 else False
671675
self.write_indent()
672-
ind = self.sequence_dash_offset # if len(self.indents) > 1 else 0
676+
cur_dash_offset = self.sequence_dash_offset
677+
if self.current_local_block_seq_indent and self.preserve_block_seqs_indents:
678+
cur_dash_offset = self.current_local_block_seq_indent
679+
ind = cur_dash_offset # if len(self.indents) > 1 else 0
673680
self.write_indicator(' ' * ind + '-', True, indention=True)
674-
if nonl or self.sequence_dash_offset + 2 > self.best_sequence_indent:
681+
if nonl or cur_dash_offset + 2 > self.best_sequence_indent:
675682
self.no_newline = True
676683
self.states.append(self.expect_block_sequence_item)
677684
self.expect_node(sequence=True)

lib/ruyaml/events.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,23 @@ def __init__(
186186

187187

188188
class SequenceStartEvent(CollectionStartEvent):
189-
__slots__ = ()
189+
__slots__ = ('block_seq_indent', )
190+
191+
def __init__(
192+
self,
193+
anchor,
194+
tag,
195+
implicit,
196+
start_mark=None,
197+
end_mark=None,
198+
flow_style=None,
199+
comment=None,
200+
block_seq_indent=None,
201+
nr_items=None,
202+
):
203+
# type: (Any, Any, Any, Any, Any, Any, Any, Any, Optional[int]) -> None
204+
CollectionStartEvent.__init__(self, anchor, tag, implicit, start_mark, end_mark, flow_style, comment, nr_items)
205+
self.block_seq_indent = block_seq_indent
190206

191207

192208
class SequenceEndEvent(CollectionEndEvent):

lib/ruyaml/main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ def __init__(
169169
self.version = None
170170
self.preserve_quotes = None
171171
self.preserve_bools = None
172+
self.preserve_block_seqs_indents = None
172173
self.allow_duplicate_keys = False # duplicate keys in map, set
173174
self.encoding = 'utf-8'
174175
self.explicit_start = None
@@ -273,6 +274,7 @@ def emitter(self):
273274
line_break=self.line_break,
274275
prefix_colon=self.prefix_colon,
275276
brace_single_entry_mapping_in_flow_sequence=self.brace_single_entry_mapping_in_flow_sequence, # NOQA
277+
preserve_block_seqs_indents=self.preserve_block_seqs_indents,
276278
dumper=self,
277279
)
278280
setattr(self, attr, _emitter)

lib/ruyaml/nodes.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,25 @@ def __init__(
121121

122122

123123
class SequenceNode(CollectionNode):
124-
__slots__ = ()
124+
__slots__ = ('block_seq_indent', )
125125
id = 'sequence'
126126

127+
def __init__(
128+
self,
129+
tag,
130+
value,
131+
start_mark=None,
132+
end_mark=None,
133+
flow_style=None,
134+
comment=None,
135+
anchor=None,
136+
):
137+
# type: (Any, Any, Any, Any, Any, Any, Any) -> None
138+
CollectionNode.__init__(
139+
self, tag, value, start_mark, end_mark, flow_style, comment, anchor
140+
)
141+
self.block_seq_indent = None
142+
127143

128144
class MappingNode(CollectionNode):
129145
__slots__ = ('merge',)

lib/ruyaml/representer.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,8 +815,19 @@ def represent_sequence(self, tag, sequence, flow_style=None):
815815
node.flow_style = self.default_flow_style
816816
else:
817817
node.flow_style = best_style
818+
self.set_block_seq_indent(node, sequence)
818819
return node
819820

821+
def set_block_seq_indent(self, node, sequence):
822+
local_block_seq_indent = 10000
823+
if not isinstance(sequence, CommentedSeq):
824+
return
825+
if not sequence.lc.data:
826+
return
827+
for lc_item in sequence.lc.data.values():
828+
local_block_seq_indent = min(local_block_seq_indent, lc_item[1] - 2) # Why '2'?
829+
node.block_seq_indent = local_block_seq_indent
830+
820831
def merge_comments(self, node, comments):
821832
# type: (Any, Any) -> Any
822833
if comments is None:

lib/ruyaml/serializer.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ def serialize_node(self, node, parent, index):
208208
implicit,
209209
flow_style=node.flow_style,
210210
comment=node.comment,
211+
block_seq_indent=node.block_seq_indent,
211212
)
212213
)
213214
index = 0

0 commit comments

Comments
 (0)