aboutsummaryrefslogtreecommitdiffstats
path: root/resources/libraries/python/model/mem2raw.py
diff options
context:
space:
mode:
Diffstat (limited to 'resources/libraries/python/model/mem2raw.py')
-rw-r--r--resources/libraries/python/model/mem2raw.py145
1 files changed, 0 insertions, 145 deletions
diff --git a/resources/libraries/python/model/mem2raw.py b/resources/libraries/python/model/mem2raw.py
deleted file mode 100644
index 543ee935e2..0000000000
--- a/resources/libraries/python/model/mem2raw.py
+++ /dev/null
@@ -1,145 +0,0 @@
-# Copyright (c) 2022 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Module for converting in-memory data into raw JSON output.
-
-CSIT and VPP PAPI are using custom data types
-that are not directly serializable into JSON.
-
-Thus, before writing the raw outpt onto disk,
-the data is recursively converted to equivalent serializable types,
-in extreme cases replaced by string representation.
-
-Validation is outside the scope of this module,
-as it should use the JSON data read from disk.
-"""
-
-import json
-import os
-
-from collections.abc import Iterable, Mapping, Set
-from enum import IntFlag
-
-
-def _pre_serialize_recursive(data):
- """Recursively sort and convert to a more serializable form.
-
- VPP PAPI code can give data with its own MACAddres type,
- or various other enum and flag types.
- The default json.JSONEncoder method raises TypeError on that.
- First point of this function is to apply str() or repr()
- to leaf values that need it.
-
- Also, PAPI responses are namedtuples, which confuses
- the json.JSONEncoder method (so it does not recurse).
- Dictization (see PapiExecutor) helps somewhat, but it turns namedtuple
- into a UserDict, which also confuses json.JSONEncoder.
- Therefore, we recursively convert any Mapping into an ordinary dict.
-
- We also convert iterables to list (sorted if the iterable was a set),
- and prevent numbers from getting converted to strings.
-
- As we are doing such low level operations,
- we also convert mapping keys to strings
- and sort the mapping items by keys alphabetically,
- except "data" field moved to the end.
-
- :param data: Object to make serializable, dictized when applicable.
- :type data: object
- :returns: Serializable equivalent of the argument.
- :rtype: object
- :raises ValueError: If the argument does not support string conversion.
- """
- # Recursion ends at scalar values, first handle irregular ones.
- if isinstance(data, IntFlag):
- return repr(data)
- if isinstance(data, bytes):
- return data.hex()
- # The regular ones are good to go.
- if isinstance(data, (str, int, float, bool)):
- return data
- # Recurse over, convert and sort mappings.
- if isinstance(data, Mapping):
- # Convert and sort alphabetically.
- ret = {
- str(key): _pre_serialize_recursive(data[key])
- for key in sorted(data.keys())
- }
- # If exists, move "data" field to the end.
- if u"data" in ret:
- data_value = ret.pop(u"data")
- ret[u"data"] = data_value
- # If exists, move "type" field at the start.
- if u"type" in ret:
- type_value = ret.pop(u"type")
- ret_old = ret
- ret = dict(type=type_value)
- ret.update(ret_old)
- return ret
- # Recurse over and convert iterables.
- if isinstance(data, Iterable):
- list_data = [_pre_serialize_recursive(item) for item in data]
- # Additionally, sets are exported as sorted.
- if isinstance(data, Set):
- list_data = sorted(list_data)
- return list_data
- # Unknown structure, attempt str().
- return str(data)
-
-
-def _pre_serialize_root(data):
- """Recursively convert to a more serializable form, tweak order.
-
- See _pre_serialize_recursive for most of changes this does.
-
- The logic here (outside the recursive function) only affects
- field ordering in the root mapping,
- to make it more human friendly.
- We are moving "version" to the top,
- followed by start time and end time.
- and various long fields (such as "log") to the bottom.
-
- Some edits are done in-place, do not trust the argument value after calling.
-
- :param data: Root data to make serializable, dictized when applicable.
- :type data: dict
- :returns: Order-tweaked version of the argument.
- :rtype: dict
- :raises KeyError: If the data does not contain required fields.
- :raises TypeError: If the argument is not a dict.
- :raises ValueError: If the argument does not support string conversion.
- """
- if not isinstance(data, dict):
- raise RuntimeError(f"Root data object needs to be a dict: {data!r}")
- data = _pre_serialize_recursive(data)
- log = data.pop(u"log")
- new_data = dict(version=data.pop(u"version"))
- new_data[u"start_time"] = data.pop(u"start_time")
- new_data[u"end_time"] = data.pop(u"end_time")
- new_data.update(data)
- new_data[u"log"] = log
- return new_data
-
-
-def write_raw_output(raw_file_path, raw_data):
- """Prepare data for serialization and dump into a file.
-
- Ancestor directories are created if needed.
-
- :param to_raw_path: Local filesystem path, including the file name.
- :type to_raw_path: str
- """
- raw_data = _pre_serialize_root(raw_data)
- os.makedirs(os.path.dirname(raw_file_path), exist_ok=True)
- with open(raw_file_path, u"wt", encoding="utf-8") as file_out:
- json.dump(raw_data, file_out, indent=1)