azure-cli-diff-tool/azure_cli_diff_tool/__init__.py (114 lines of code) (raw):

# ----------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for # license information. # ----------------------------------------------------------------------------- # pylint: disable=too-many-lines # pylint: disable=too-many-statements import os import json import time from enum import Enum import logging from deepdiff import DeepDiff from .meta_change_detect import MetaChangeDetect from .utils import get_blob_config, load_blob_config_file, get_target_version_modules, get_target_version_module, \ extract_module_name_from_meta_file, export_meta_changes_to_csv, export_meta_changes_to_json, \ export_meta_changes_to_dict, expand_deprecate_obj __VERSION__ = '0.1.0' logger = logging.getLogger(__name__) class DiffExportFormat(Enum): DICT = "dict" TEXT = "text" TREE = "tree" def diff_export_format_choices(): return [form.value for form in DiffExportFormat] def check_meta_tool_compatibility(meta_version): if not meta_version: return False meta_version_vec = meta_version.split(".") tool_version_vec = __VERSION__.split(".") version_outdated = False for ind, v in enumerate(meta_version_vec): if v.isdigit() and tool_version_vec[ind].isdigit() and int(v) > int(tool_version_vec[ind]): version_outdated = True return version_outdated def meta_diff(base_meta_file, diff_meta_file, only_break=False, output_type="text", output_file=None): if not os.path.exists(base_meta_file): raise Exception("base meta file needed") if not os.path.exists(diff_meta_file): raise Exception("diff meta file needed") with open(base_meta_file, "r") as g: command_tree_before = json.load(g) with open(diff_meta_file, "r") as g: command_tree_after = json.load(g) if command_tree_before.get("compat_version", None) \ and check_meta_tool_compatibility(command_tree_before["compat_version"]): raise Exception("Please update your azure cli diff tool") if command_tree_after.get("compat_version", None) \ and check_meta_tool_compatibility(command_tree_after["compat_version"]): raise Exception("Please update your azure cli diff tool") expand_deprecate_obj(command_tree_before) expand_deprecate_obj(command_tree_after) diff = DeepDiff(command_tree_before, command_tree_after, exclude_paths=["root['module_name']"]) if not diff: print(f"No meta diffs from {diff_meta_file} to {base_meta_file}") return export_meta_changes_to_json(None, output_file) else: detected_changes = MetaChangeDetect(diff, command_tree_before, command_tree_after) detected_changes.check_deep_diffs() result = detected_changes.export_meta_changes(only_break, output_type) return export_meta_changes_to_json(result, output_file) def version_diff(base_version, diff_version, only_break=False, version_diff_file=None, use_cache=False, output_type="dict", target_module=None): config = load_blob_config_file() blob_url, path_prefix, index_file = get_blob_config(config) download_base_start = time.time() if target_module: base_version_module_list = get_target_version_module(blob_url, path_prefix, base_version, target_module, use_cache) else: base_version_module_list = get_target_version_modules(blob_url, path_prefix, index_file, base_version, use_cache) download_base_end = time.time() logger.info("base version {} meta files download using {} sec".format(base_version, download_base_end - download_base_start)) if target_module: get_target_version_module(blob_url, path_prefix, diff_version, target_module, use_cache) else: get_target_version_modules(blob_url, path_prefix, index_file, diff_version, use_cache) download_target_end = time.time() logger.info("diff version {} meta files download using {} sec".format(diff_version, download_target_end - download_base_end)) version_diffs = [] for _, base_meta_file_full_path, base_meta_file in base_version_module_list: module_name = extract_module_name_from_meta_file(base_meta_file) if not module_name: continue if target_module and module_name != target_module: continue diff_meta_file_full_path = os.path.join(os.getcwd(), path_prefix + diff_version, base_meta_file) if not os.path.exists(diff_meta_file_full_path): print(f"Module {module_name} removed for {diff_version}") continue with open(base_meta_file_full_path, "r") as g: command_tree_before = json.load(g) with open(diff_meta_file_full_path, "r") as g: command_tree_after = json.load(g) if command_tree_before.get("compat_version", None) \ and check_meta_tool_compatibility(command_tree_before["compat_version"]): raise Exception("Please update your azure cli diff tool") if command_tree_after.get("compat_version", None) \ and check_meta_tool_compatibility(command_tree_after["compat_version"]): raise Exception("Please update your azure cli diff tool") expand_deprecate_obj(command_tree_before) expand_deprecate_obj(command_tree_after) diff = DeepDiff(command_tree_before, command_tree_after) if not diff: print(f"No meta diffs from version: {diff_version}/{base_meta_file} for module: {module_name}") continue detected_changes = MetaChangeDetect(diff, command_tree_before, command_tree_after) detected_changes.check_deep_diffs() diff_objs = detected_changes.export_meta_changes(only_break, "dict") mod_obj = {"module": module_name} for obj in diff_objs: obj.update(mod_obj) version_diffs.append(obj) meta_change_end = time.time() logger.info("meta file diffs using {} sec".format(meta_change_end - download_target_end)) if output_type == "dict": return export_meta_changes_to_dict(version_diffs, version_diff_file) return export_meta_changes_to_csv(version_diffs, version_diff_file)