Skip to content

Commit

Permalink
Enable yaml-diff to detect YAML Tag changes
Browse files Browse the repository at this point in the history
  • Loading branch information
wwkimball committed Nov 7, 2020
1 parent 28e620d commit c5e0038
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 16 deletions.
25 changes: 13 additions & 12 deletions yamlpath/differ/diffentry.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import json
from typing import Any

from ruamel.yaml.comments import CommentedBase
from ruamel.yaml.comments import CommentedBase, TaggedScalar

from yamlpath.common import Parsers
from yamlpath.enums import PathSeperators
Expand All @@ -26,6 +26,7 @@ def __init__(
self._path: YAMLPath = path
self._lhs: Any = lhs
self._rhs: Any = rhs
self._key_tag = kwargs.pop("key_tag", None)
self._set_index(lhs, rhs, **kwargs)
self._verbose = False

Expand All @@ -47,8 +48,11 @@ def __str__(self) -> str:
"""Get the string representation of this object."""
diffaction = self._action
path = self._path if self._path else "-"
output = "{}{} {}\n".format(
diffaction, self._index if self.verbose else "", path)
key_tag = ""
if self._key_tag:
key_tag = " {}".format(self._key_tag)
output = "{}{} {}{}\n".format(
diffaction, self._index if self.verbose else "", path, key_tag)
if diffaction is DiffActions.ADD:
output += DiffEntry._present_data(self._rhs, ">")
elif diffaction is DiffActions.CHANGE:
Expand Down Expand Up @@ -105,13 +109,6 @@ def verbose(self, value: bool) -> None:
if value != self.verbose:
self._verbose = value

@classmethod
def _jsonify_data(cls, data: Any) -> str:
"""Generate JSON representation of data."""
if isinstance(data, (list, dict)):
return json.dumps(Parsers.jsonify_yaml_data(data))
return str(data)

@classmethod
def _get_lc(cls, data: Any) -> str:
"""Get the line.column of a data element."""
Expand All @@ -135,7 +132,11 @@ def _get_index(cls, data: Any, parent: Any) -> str:
@classmethod
def _present_data(cls, data: Any, prefix: str) -> str:
"""Stringify data."""
return "{} {}".format(
data_tag = ""
if isinstance(data, TaggedScalar) and data.tag.value:
data_tag = "{} ".format(data.tag.value)
return "{} {}{}".format(
prefix,
DiffEntry._jsonify_data(data).strip().replace(
data_tag,
json.dumps(Parsers.jsonify_yaml_data(data)).strip().replace(
"\n", "\n{} ".format(prefix)))
24 changes: 22 additions & 2 deletions yamlpath/differ/differ.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from itertools import zip_longest
from typing import Any, Dict, Generator, List, Optional, Tuple

from ruamel.yaml.comments import TaggedScalar

from yamlpath import YAMLPath
from yamlpath.wrappers import ConsolePrinter, NodeCoords
from yamlpath.eyaml import EYAMLProcessor
Expand Down Expand Up @@ -151,6 +153,22 @@ def _diff_dicts(self, path: YAMLPath, lhs: dict, rhs: dict) -> None:
prefix="Differ::_diff_dicts: ",
data=rhs)

# Check first for a difference in YAML Tag
lhs_tag = lhs.tag.value if hasattr(lhs, "tag") else None
rhs_tag = rhs.tag.value if hasattr(rhs, "tag") else None
if lhs_tag != rhs_tag:
self.logger.debug(
"Dictionaries have different YAML Tags; {} != {}:".format(
lhs_tag, rhs_tag),
prefix="Differ::_diff_dicts: ")
self._diffs.append(
DiffEntry(
DiffActions.DELETE, path, lhs, None, key_tag=lhs_tag))
self._diffs.append(
DiffEntry(
DiffActions.ADD, path, None, rhs, key_tag=rhs_tag))
return

lhs_keys = set(lhs)
rhs_keys = set(rhs)
lhs_key_indicies = Differ._get_key_indicies(lhs)
Expand Down Expand Up @@ -186,7 +204,8 @@ def _diff_dicts(self, path: YAMLPath, lhs: dict, rhs: dict) -> None:
DiffEntry(
DiffActions.DELETE, next_path, lhs[key], None,
lhs_parent=lhs, lhs_iteration=lhs_key_indicies[key],
rhs_parent=rhs))
rhs_parent=rhs,
key_tag=key.tag.value if hasattr(key, "tag") else None))

# Look for new keys
for key in rhs_keys - lhs_keys:
Expand All @@ -196,7 +215,8 @@ def _diff_dicts(self, path: YAMLPath, lhs: dict, rhs: dict) -> None:
DiffEntry(
DiffActions.ADD, next_path, None, rhs[key],
lhs_parent=lhs,
rhs_parent=rhs, rhs_iteration=rhs_key_indicies[key]))
rhs_parent=rhs, rhs_iteration=rhs_key_indicies[key],
key_tag=key.tag.value if hasattr(key, "tag") else None))

def _diff_synced_lists(self, path: YAMLPath, lhs: list, rhs: list) -> None:
"""Diff two synchronized lists."""
Expand Down
27 changes: 25 additions & 2 deletions yamlpath/wrappers/consoleprinter.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,13 @@ def _debug_get_anchor(data: Any) -> str:
if hasattr(data, "anchor") and data.anchor.value is not None
else "")

@staticmethod
def _debug_get_tag(data: Any) -> str:
"""Helper for debug."""
return (data.tag.value
if hasattr(data, "tag") and data.tag.value is not None
else "")

@staticmethod
def _debug_dump(data: Any, **kwargs) -> Generator[str, None, None]:
"""Helper for debug."""
Expand Down Expand Up @@ -334,6 +341,20 @@ def _debug_get_kv_anchors(key: Any, value: Any) -> str:
display_anchor = "(_,{})".format(val_anchor)
return display_anchor

@staticmethod
def _debug_get_kv_tags(key: Any, value: Any) -> str:
"""Helper for debug."""
key_tag = ConsolePrinter._debug_get_tag(key)
val_tag = ConsolePrinter._debug_get_tag(value)
display_tag = ""
if key_tag and val_tag:
display_tag = "<{},{}>".format(key_tag, val_tag)
elif key_tag:
display_tag = "<{},_>".format(key_tag)
elif val_tag:
display_tag = "<_,{}>".format(val_tag)
return display_tag

@staticmethod
def _debug_dict(
data: Union[Dict, CommentedMap], **kwargs
Expand All @@ -354,10 +375,12 @@ def _debug_dict(
if key in local_keys
else "<<:{}:>>".format(key))
display_anchor = ConsolePrinter._debug_get_kv_anchors(key, val)
kv_prefix = "{}[{}]{}".format(prefix, display_key, display_anchor)
display_tag = ConsolePrinter._debug_get_kv_tags(key, val)
kv_prefix = "{}[{}]{}{}".format(
prefix, display_key, display_anchor, display_tag)

for line in ConsolePrinter._debug_dump(
val, prefix=kv_prefix, print_type=True, print_tag=True,
val, prefix=kv_prefix, print_type=True, print_tag=False,
print_anchor=False
):
yield line

0 comments on commit c5e0038

Please sign in to comment.