Skip to content
Merged
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ to activate it.
## Version History / Release Notes:

* Unreleased
* Preserve duck-typed mapping contents without testing their truth value.
* Preserve duck-typed array contents without testing their truth value.
* Honor explicit false-valued callable parsing hooks and default encoders
without testing their truth value.
Expand Down
3 changes: 0 additions & 3 deletions json5/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -871,9 +871,6 @@ def _encode_non_basic_type(self, obj, seen: Set, level: int) -> str:
return s

def _encode_dict(self, obj: Any, seen: set, level: int) -> str:
if not obj:
return '{}'

indent_str, end_str = self._spacers(level)
item_sep = self.item_separator + indent_str
kv_sep = self.kv_separator
Expand Down
58 changes: 55 additions & 3 deletions tests/lib_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,61 @@ def __bool__(self): # pragma: no cover
)
self.assertEqual(json5.loads(result), values)

def test_duck_mapping_without_truth_value(self):
class Mapping:
def __init__(self, values):
self.values = values

def keys(self):
return iter(self.values)

def __getitem__(self, key):
return self.values[key]

def __bool__(self):
raise ValueError(
'The truth value is undefined'
) # pragma: no cover

for values in ({}, {'b': 0, 'a': [1, 2]}):
for indent in (None, 0, 2, '\t'):
for trailing_commas in (False, True):
for sort_keys in (False, True):
with self.subTest(
values=values,
indent=indent,
trailing_commas=trailing_commas,
sort_keys=sort_keys,
):
options = {
'indent': indent,
'trailing_commas': trailing_commas,
'sort_keys': sort_keys,
}
self.assertEqual(
json5.dumps(
Mapping(values),
use_duck_typing=True,
**options,
),
json5.dumps(values, **options),
)

def test_false_valued_duck_mapping(self):
class Mapping:
def keys(self):
return ['answer']

def __getitem__(self, key):
return {'answer': 42}[key]

def __bool__(self):
return False # pragma: no cover

self.assertEqual(
json5.dumps(Mapping(), use_duck_typing=True), '{answer: 42}'
)

def test_invalid_collection(self):
# Check that something that isn't actually an array or a dict doesn't
# work.
Expand Down Expand Up @@ -785,9 +840,6 @@ def keys(self):
def __getitem__(self, k):
return {'a': 1, 'b': 2}[k]

def __len__(self):
return 2

value = MyDict()
self.assertRaises(TypeError, json5.dumps, value)
self.assertEqual(
Expand Down