Skip to content

Commit

Permalink
fix(yaml): emit null, not empty scalars
Browse files Browse the repository at this point in the history
This is the null representation users expect.
It was how Remarshal worked with PyYAML.

The choice of how to implement it
is per the suggestion of the developer of ruamel.yaml
on https://stackoverflow.com/questions/44313992/.
  • Loading branch information
dbohdan committed Oct 13, 2024
1 parent 05b2804 commit 74c9a61
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/remarshal/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,10 @@ def stringify_null(x: Any) -> Any:
raise ValueError(msg)


def _yaml_represent_none(self, data):
return self.represent_scalar("tag:yaml.org,2002:null", "null")


def _encode_yaml(data: Document, *, yaml_options: YAMLOptions) -> str:
yaml = ruamel.yaml.YAML()
yaml.default_flow_style = False
Expand All @@ -654,6 +658,8 @@ def _encode_yaml(data: Document, *, yaml_options: YAMLOptions) -> str:
yaml.indent = yaml_options.indent
yaml.width = yaml_options.width

yaml.representer.add_representer(type(None), _yaml_represent_none)

try:
out = StringIO()
yaml.dump(
Expand Down
2 changes: 1 addition & 1 deletion tests/bool-null-key.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
True: foo
false: oof
another: bar
NULL: "nothin'"
NULL: nothin'
3 changes: 3 additions & 0 deletions tests/null.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"foo": null
}
1 change: 1 addition & 0 deletions tests/null.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo: null
17 changes: 16 additions & 1 deletion tests/test_remarshal.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#! /usr/bin/env python
# Remarshal, a utility to convert between serialization formats.
# Copyright (c) 2014-2020, 2023 D. Bohdan
# Copyright (c) 2014-2020, 2023-2024 D. Bohdan
# License: MIT

from __future__ import annotations
Expand Down Expand Up @@ -364,6 +364,11 @@ def test_binary_to_yaml(self, convert_and_read) -> None:
def test_binary_to_cbor(self, convert_and_read) -> None:
convert_and_read("bin.msgpack", "msgpack", "cbor")

def test_yaml_null(self, convert_and_read) -> None:
output = convert_and_read("null.json", "json", "yaml")
reference = read_file("null.yaml")
assert output == reference

def test_yaml_style_default(self, convert_and_read) -> None:
output = convert_and_read("long-line.json", "json", "yaml")
reference = read_file("long-line-default.yaml")
Expand Down Expand Up @@ -544,6 +549,16 @@ def test_yaml2toml_bool_null_key(self, convert_and_read) -> None:
reference = read_file("bool-null-key.toml")
assert output == reference

def test_yaml2yaml_bool_null_key(self, convert_and_read) -> None:
output = convert_and_read(
"bool-null-key.yaml",
"yaml",
"yaml",
)
reference = read_file("bool-null-key.yaml")

assert output == reference.lower()

def test_yaml2toml_timestamp_key(self, convert_and_read) -> None:
output = convert_and_read(
"timestamp-key.yaml",
Expand Down

0 comments on commit 74c9a61

Please sign in to comment.