Skip to content

Commit 7ad18f5

Browse files
author
guibog
committed
Add preserve_block_seqs_indents
1 parent 0a12be2 commit 7ad18f5

File tree

8 files changed

+192
-4
lines changed

8 files changed

+192
-4
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
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+
class ScalarNodePositioned(ScalarNode):
17+
lc_position = None
18+
19+
20+
class ScalarBooleanStable(ScalarBoolean):
21+
22+
def __new__(cls: Any, boolval, origrepr, anchor=None) -> Any:
23+
b = ScalarBoolean.__new__(cls, boolval, anchor=anchor)
24+
b.original_bool_repr = origrepr
25+
return b
26+
27+
28+
#def represent_list2(self, data):
29+
# dedede
30+
# RoundTripRepresenter.add_representer(CommentedSeq, represent_list2)
31+
32+
33+
class BetterRoundTripConstructor(RoundTripConstructor):
34+
keep_bool_repr = True
35+
36+
37+
class BetterRoundTripRepresenter(RoundTripRepresenter):
38+
def represent_bool(self, data, anchor=None):
39+
ret = self.represent_scalar('tag:yaml.org,2002:bool', data.original_bool_repr, anchor=anchor)
40+
return ret
41+
42+
def TOTO_represent_sequence(self, tag, data):
43+
node = super().represent_sequence(tag, data)
44+
print(44, self, tag, data, node)
45+
# print(45, data.lc, data.lc.data)
46+
local_block_seq_ident = -1
47+
48+
49+
#BetterRoundTripConstructor.add_constructor('tag:yaml.org,2002:bool', BetterRoundTripConstructor.construct_yaml_bool)
50+
#BetterRoundTripRepresenter.add_representer(ScalarBooleanStable, BetterRoundTripRepresenter.represent_bool)
51+
52+
53+
def round_trip_stabler(
54+
inp,
55+
outp=None,
56+
):
57+
if outp is None:
58+
outp = inp
59+
doutp = dedent(outp)
60+
yaml = ruyaml.YAML()
61+
yaml.preserve_quotes = True
62+
yaml.preserve_block_seqs_indents = True
63+
data = yaml.load(doutp)
64+
buf = io.StringIO()
65+
yaml.dump(data, stream=buf)
66+
res = buf.getvalue()
67+
assert res == doutp
68+
69+
70+
class TestStability:
71+
72+
def test_blockseq1(self):
73+
round_trip(
74+
"""
75+
a:
76+
- a1
77+
- a2
78+
"""
79+
)
80+
81+
@pytest.mark.xfail(strict=True)
82+
def test_blockseq2(self):
83+
round_trip(
84+
"""
85+
a:
86+
- a1
87+
- a2
88+
"""
89+
)
90+
91+
@pytest.mark.xfail(strict=True)
92+
def test_blockseq3(self):
93+
round_trip(
94+
"""
95+
a:
96+
- a1
97+
- a2
98+
b:
99+
- b1
100+
- b2
101+
"""
102+
)
103+
104+
class TestStabilityStabler:
105+
106+
def test_blockseq1(self):
107+
round_trip_stabler(
108+
"""
109+
a:
110+
- a1
111+
- a2
112+
"""
113+
)
114+
115+
def test_blockseq2(self):
116+
round_trip_stabler(
117+
"""
118+
a:
119+
- a1
120+
- a2
121+
"""
122+
)
123+
124+
def test_blockseq3(self):
125+
round_trip_stabler(
126+
"""
127+
a:
128+
- a1
129+
- a2
130+
b:
131+
- b1
132+
- b2
133+
"""
134+
)

lib/ruyaml/dumper.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ def __init__(
203203
allow_unicode=allow_unicode,
204204
line_break=line_break,
205205
block_seq_indent=block_seq_indent,
206+
preserve_block_seqs_indents=preserve_block_seqs_indents,
206207
top_level_colon_align=top_level_colon_align,
207208
prefix_colon=prefix_colon,
208209
dumper=self,

lib/ruyaml/emitter.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ 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
):
122123
# type: (StreamType, Any, Optional[int], Optional[int], Optional[bool], Any, Optional[int], Optional[bool], Any, Optional[bool], Any) -> None # NOQA
@@ -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+
nr_items=None,
201+
block_seq_indent=None,
202+
):
203+
# type: (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)