Skip to content

Commit 0a12be2

Browse files
author
guibog
committed
Add preserve_bools
1 parent c3a5f20 commit 0a12be2

File tree

5 files changed

+100
-11
lines changed

5 files changed

+100
-11
lines changed

_test/test_bools.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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_bools = 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_lowercase_boolean(self):
36+
round_trip(
37+
"""
38+
- true
39+
"""
40+
)
41+
42+
@pytest.mark.xfail(strict=True)
43+
def test_uppercase_boolean(self):
44+
round_trip(
45+
"""
46+
- True
47+
"""
48+
)
49+
50+
# @pytest.mark.xfail(strict=True) # Why not failing??
51+
def test_yes_boolean(self):
52+
round_trip(
53+
"""
54+
- yes
55+
"""
56+
)
57+
58+
def test_lowercase_boolean2(self):
59+
round_trip_stabler(
60+
"""
61+
- true
62+
"""
63+
)
64+
65+
def test_uppercase_boolean2(self):
66+
round_trip_stabler(
67+
"""
68+
- True
69+
"""
70+
)
71+
72+
def test_yes_boolean2(self):
73+
round_trip_stabler(
74+
"""
75+
- yes
76+
"""
77+
)

lib/ruyaml/constructor.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class BaseConstructor:
7575
yaml_constructors = {} # type: Dict[Any, Any]
7676
yaml_multi_constructors = {} # type: Dict[Any, Any]
7777

78-
def __init__(self, preserve_quotes=None, loader=None):
78+
def __init__(self, preserve_quotes=None, loader=None, preserve_bools=None):
7979
# type: (Optional[bool], Any) -> None
8080
self.loader = loader
8181
if (
@@ -91,6 +91,7 @@ def __init__(self, preserve_quotes=None, loader=None):
9191
self.state_generators = [] # type: List[Any]
9292
self.deep_construct = False
9393
self._preserve_quotes = preserve_quotes
94+
self._preserve_bools = preserve_bools
9495
self.allow_duplicate_keys = False
9596

9697
@property
@@ -1862,8 +1863,8 @@ def construct_yaml_timestamp(self, node, values=None):
18621863
def construct_yaml_bool(self, node):
18631864
# type: (Any) -> Any
18641865
b = SafeConstructor.construct_yaml_bool(self, node)
1865-
if node.anchor:
1866-
return ScalarBoolean(b, anchor=node.anchor)
1866+
if node.anchor or self._preserve_bools:
1867+
return ScalarBoolean(b, anchor=node.anchor, orig_repr=node.value)
18671868
return b
18681869

18691870

lib/ruyaml/main.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ def __init__(
168168
self.prefix_colon = None
169169
self.version = None
170170
self.preserve_quotes = None
171+
self.preserve_bools = None
171172
self.allow_duplicate_keys = False # duplicate keys in map, set
172173
self.encoding = 'utf-8'
173174
self.explicit_start = None
@@ -242,7 +243,9 @@ def constructor(self):
242243
# type: () -> Any
243244
attr = '_' + sys._getframe().f_code.co_name
244245
if not hasattr(self, attr):
245-
cnst = self.Constructor(preserve_quotes=self.preserve_quotes, loader=self)
246+
cnst = self.Constructor(preserve_quotes=self.preserve_quotes,
247+
preserve_bools=self.preserve_bools,
248+
loader=self)
246249
cnst.allow_duplicate_keys = self.allow_duplicate_keys
247250
setattr(self, attr, cnst)
248251
return getattr(self, attr)

lib/ruyaml/representer.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,16 @@ def represent_binary(self, data):
254254

255255
def represent_bool(self, data, anchor=None):
256256
# type: (Any, Optional[Any]) -> Any
257-
try:
258-
value = self.dumper.boolean_representation[bool(data)] # type: ignore
259-
except AttributeError:
260-
if data:
261-
value = 'true'
262-
else:
263-
value = 'false'
257+
if getattr(data, 'yaml_orig_repr', None) is not None:
258+
value = data.yaml_orig_repr
259+
else:
260+
try:
261+
value = self.dumper.boolean_representation[bool(data)] # type: ignore
262+
except AttributeError:
263+
if data:
264+
value = 'true'
265+
else:
266+
value = 'false'
264267
return self.represent_scalar('tag:yaml.org,2002:bool', value, anchor=anchor)
265268

266269
def represent_int(self, data):

lib/ruyaml/scalarbool.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,15 @@
1818

1919

2020
class ScalarBoolean(int):
21+
yaml_orig_repr = None
22+
2123
def __new__(cls, *args, **kw):
2224
# type: (Any, Any, Any) -> Any
2325
anchor = kw.pop('anchor', None)
26+
orig_repr = kw.pop('orig_repr', None)
2427
b = int.__new__(cls, *args, **kw)
28+
if orig_repr is not None:
29+
b.yaml_orig_repr = orig_repr
2530
if anchor is not None:
2631
b.yaml_set_anchor(anchor, always_dump=True)
2732
return b

0 commit comments

Comments
 (0)