Blame SOURCES/BZ_1806474-sort-pretty-state-with-priority.patch

47b589
From d0bfae4171f0d280241949a928654c84e63ed006 Mon Sep 17 00:00:00 2001
47b589
From: Gris Ge <fge@redhat.com>
47b589
Date: Mon, 29 Jun 2020 22:30:03 +0800
47b589
Subject: [PATCH] pretty state: Dumping state in the sorted order with priority
47b589
47b589
For OVS bond port, we would like the `name` been shown before other
47b589
properties.
47b589
47b589
To achieve that, we sort the dict keys and honoring the priority list which
47b589
means keys in `PRIORITY_LIST` will be shown before others.
47b589
47b589
Currently the `PRIORITY_LIST` is:
47b589
`("name", "type", "state", "enabled", "dns", "route-rules", "routes",
47b589
  "interfaces")`
47b589
47b589
Test cases added.
47b589
47b589
Signed-off-by: Gris Ge <fge@redhat.com>
47b589
Signed-off-by: Till Maas <till@redhat.com>
47b589
---
47b589
 libnmstate/prettystate.py | 94 ++++++++++++++++++---------------------
47b589
 1 file changed, 43 insertions(+), 51 deletions(-)
47b589
47b589
diff --git a/libnmstate/prettystate.py b/libnmstate/prettystate.py
47b589
index da57618..10e22d6 100644
47b589
--- a/libnmstate/prettystate.py
47b589
+++ b/libnmstate/prettystate.py
47b589
@@ -1,5 +1,5 @@
47b589
 #
47b589
-# Copyright (c) 2018-2019 Red Hat, Inc.
47b589
+# Copyright (c) 2018-2020 Red Hat, Inc.
47b589
 #
47b589
 # This file is part of nmstate
47b589
 #
47b589
@@ -17,15 +17,29 @@
47b589
 # along with this program. If not, see <https://www.gnu.org/licenses/>.
47b589
 #
47b589
 
47b589
-from collections import OrderedDict
47b589
+from collections.abc import Mapping
47b589
+from collections.abc import Sequence
47b589
 from copy import deepcopy
47b589
 import difflib
47b589
 import json
47b589
-from operator import itemgetter
47b589
 
47b589
 import yaml
47b589
 
47b589
-from libnmstate.schema import Constants
47b589
+from .schema import DNS
47b589
+from .schema import Route
47b589
+from .schema import RouteRule
47b589
+from .schema import Interface
47b589
+
47b589
+PRIORITY_LIST = (
47b589
+    "name",
47b589
+    "type",
47b589
+    "state",
47b589
+    "enabled",
47b589
+    DNS.KEY,
47b589
+    RouteRule.KEY,
47b589
+    Route.KEY,
47b589
+    Interface.KEY,
47b589
+)
47b589
 
47b589
 
47b589
 def format_desired_current_state_diff(desired_state, current_state):
47b589
@@ -57,8 +71,8 @@ def format_desired_current_state_diff(desired_state, current_state):
47b589
 
47b589
 class PrettyState:
47b589
     def __init__(self, state):
47b589
-        yaml.add_representer(OrderedDict, represent_ordereddict)
47b589
-        self.state = order_state(deepcopy(state))
47b589
+        yaml.add_representer(dict, represent_dict)
47b589
+        self.state = _sort_with_priority(state)
47b589
 
47b589
     @property
47b589
     def yaml(self):
47b589
@@ -71,35 +85,18 @@ class PrettyState:
47b589
         return json.dumps(self.state, indent=4, separators=(",", ": "))
47b589
 
47b589
 
47b589
-def represent_ordereddict(dumper, data):
47b589
+def represent_dict(dumper, data):
47b589
+    """
47b589
+    Represent dictionary with insert order
47b589
     """
47b589
-    Represent OrderedDict as regular dictionary
47b589
-
47b589
-    Source: https://stackoverflow.com/questions/16782112/can-pyyaml-dump-dict-items-in-non-alphabetical-order
47b589
-    """  # noqa: E501
47b589
     value = []
47b589
 
47b589
     for item_key, item_value in data.items():
47b589
         node_key = dumper.represent_data(item_key)
47b589
         node_value = dumper.represent_data(item_value)
47b589
-
47b589
         value.append((node_key, node_value))
47b589
 
47b589
-    return yaml.nodes.MappingNode(u"tag:yaml.org,2002:map", value)
47b589
-
47b589
-
47b589
-def order_state(state):
47b589
-    iface_states = state.pop(Constants.INTERFACES, None)
47b589
-
47b589
-    state = order_iface_state(state)
47b589
-
47b589
-    if iface_states is not None:
47b589
-        state[Constants.INTERFACES] = [
47b589
-            order_iface_state(iface_state)
47b589
-            for iface_state in sorted(iface_states, key=itemgetter("name"))
47b589
-        ]
47b589
-
47b589
-    return state
47b589
+    return yaml.nodes.MappingNode("tag:yaml.org,2002:map", value)
47b589
 
47b589
 
47b589
 def represent_unicode(_, data):
47b589
@@ -112,30 +109,25 @@ def represent_unicode(_, data):
47b589
     """
47b589
 
47b589
     return yaml.ScalarNode(
47b589
-        tag=u"tag:yaml.org,2002:str", value=data.encode("utf-8")
47b589
+        tag="tag:yaml.org,2002:str", value=data.encode("utf-8")
47b589
     )
47b589
 
47b589
 
47b589
-def order_iface_state(iface_state):
47b589
-    ordered_state = OrderedDict()
47b589
-
47b589
-    for setting in ("name", "type", "state"):
47b589
-        try:
47b589
-            ordered_state[setting] = iface_state.pop(setting)
47b589
-        except KeyError:
47b589
-            pass
47b589
-
47b589
-    for key, value in order_dict(iface_state).items():
47b589
-        ordered_state[key] = value
47b589
-
47b589
-    return ordered_state
47b589
-
47b589
-
47b589
-def order_dict(dict_):
47b589
-    ordered_dict = OrderedDict()
47b589
-    for key, value in sorted(dict_.items()):
47b589
-        if isinstance(value, dict):
47b589
-            value = order_dict(value)
47b589
-        ordered_dict[key] = value
47b589
-
47b589
-    return ordered_dict
47b589
+def _sort_with_priority(data):
47b589
+    if isinstance(data, Sequence) and not isinstance(data, str):
47b589
+        return [_sort_with_priority(item) for item in data]
47b589
+    elif isinstance(data, Mapping):
47b589
+        new_data = {}
47b589
+        for key in sorted(data.keys(), key=_sort_with_priority_key_func):
47b589
+            new_data[key] = _sort_with_priority(data[key])
47b589
+        return new_data
47b589
+    else:
47b589
+        return deepcopy(data)
47b589
+
47b589
+
47b589
+def _sort_with_priority_key_func(key):
47b589
+    try:
47b589
+        priority = PRIORITY_LIST.index(key)
47b589
+    except ValueError:
47b589
+        priority = len(PRIORITY_LIST)
47b589
+    return (priority, key)
47b589
-- 
47b589
2.27.0
47b589