Source code for tree.changelog

# !/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Filename: utils.py
# Project: tree
# Author: Brian Cherinka
# Created: Tuesday, 17th March 2020 11:22:02 am
# License: BSD 3-clause "New" or "Revised" License
# Copyright (c) 2020 Brian Cherinka
# Last Modified: Tuesday, 17th March 2020 1:41:46 pm
# Modified By: Brian Cherinka


from __future__ import print_function, division, absolute_import
import os
import six
from tree import Tree


[docs] def compute_changelog(new, old, pprint=None, to_list=None, remove_sas=True, include_paths=True, paths_only=None): ''' Compute the difference between two Tree environments Finds and prints the difference between two tree environment configurations. Accepts either string names of config files, e.g. "dr16" and "dr15", or the preloaded `Tree` configs, e.g. `Tree(config='dr16')`. By default returns a dictionary of changes or use the `pprint` keyword to return a formatted print-friendly string for display. The `to_list` keyword returns a print-formatted list of strings parse parseable by `docutree` for Sphinx docs. Set `include_paths` to True to include a changelog of the `sdss_access` path definitions. Parameters: new (str|Tree): The new tree enviroment to compare old (str|Tree): The old tree environment to compare pprint (bool): If True, returns a single joined string for printing. Default is False. to_list (bool): If True, returns a list of strings formatted for printing. Default is False. remove_sas (bool): If True, removes the SAS_BASE_DIR from environment values. Default is True. include_paths (bool): If True, includes changes to the sdss_access PATHS section. Default is True. paths_only (bool): If True, returns only changes in sdss_access PATHS section. Default is False. Returns: A dictionary of relevant changes between the two releases Example: >>> # print the differences DR16 and DR15 >>> diffs = compute_changelog('dr16', 'dr15', pprint=True) >>> print(diffs) ''' # compute the environment changelog dictionary cl_dict = compute_environment_changes(new, old, remove_sas=remove_sas) # compute and add the paths changelog dictionary if include_paths or paths_only: path_dict = compute_path_changes(new, old, prepend_header=paths_only) cl_dict.update(path_dict) # return PATHS section only if paths_only: cl_dict = cl_dict.copy() cl_dict.pop('environment') if pprint or to_list: return print_paths(cl_dict, to_string=not to_list, prepend_header=paths_only) return cl_dict if pprint or to_list: return print_environment(cl_dict, to_string=not to_list) return cl_dict
[docs] def compute_environment_changes(new, old, remove_sas=True): ''' Compute the difference between two Tree environments Compares two tree environment configurations and returns a dictionary with keys `new`, `removed`, and `changes` indicating newly added environments, newly removed environments, and environments where environment variable definitions have changed. Accepts either string names of config files, e.g. "dr16" and "dr15", or the preloaded `Tree` configs, e.g. `Tree(config='dr16')`. Parameters: new (str|Tree): The new tree enviroment to compare old (str|Tree): The old tree environment to compare remove_sas (bool): If True, removes the SAS_BASE_DIR from environment values. Default is True. Returns: A dictionary of relevant changes between the two releases ''' dd = {'environment': {'new': {}, 'changes': {}, 'removed': {}}} if isinstance(new, six.string_types): new = Tree(config=new.lower()) if isinstance(old, six.string_types): old = Tree(config=old.lower()) new_envs = new.environ.keys() old_envs = old.environ.keys() new_name = new.environ['default']['name'] old_name = old.environ['default']['name'] sas = os.getenv("SAS_BASE_DIR") dd['releases'] = {'new': new_name, 'old': old_name} # find unique new enviroments unique_new_envs = set(new_envs) - set(old_envs) for env in unique_new_envs: dd['environment']['new'][env] = {} for k, v in new.environ[env].items(): if remove_sas: v = v.split(sas)[-1] dd['environment']['new'][env][k.upper()] = v # find unique old enviroments unique_old_envs = set(old_envs) - set(new_envs) for env in unique_old_envs: dd['environment']['removed'][env] = {} for k, v in old.environ[env].items(): if remove_sas: v = v.split(sas)[-1] dd['environment']['removed'][env][k.upper()] = v # find new or updated environment variables for env in new_envs: # skip the default if env == 'default' or env not in old.environ: continue uniq_vars = set(new.environ[env].keys()) - set(old.environ[env].keys()) if not uniq_vars: continue vbase = [v.split(os.path.join(sas, new_name))[-1] for v in new.environ[env].values()] voldbase = [v.split(os.path.join(sas, old_name))[-1] for v in old.environ[env].values()] changes = set(vbase) - set(voldbase) if not changes: continue dd['environment']['changes'][env] = {} for k, v in new.environ[env].items(): vold = old.environ[env].get(k, None) if vold: vbase = v.split(os.path.join(sas, new_name))[-1] voldbase = vold.split(os.path.join(sas, old_name))[-1] if vbase != voldbase: dd['environment']['changes'][env][k.upper()] = {'from': voldbase, 'to': vbase} else: if remove_sas: v = v.split(sas)[-1] dd['environment']['changes'][env][k.upper()] = v return dd
[docs] def compute_path_changes(new, old, prepend_header=None): ''' Compute the difference between two Tree PATH sections Compares two tree PATH ini sections from the given environment configurations and returns adictionary with keys `new`, and `updated`, indicating newly added paths, and any paths that have been modified from the last release. Accepts either string names of config files, e.g. "dr16" and "dr15", or the preloaded `Tree` configs, e.g. `Tree(config='dr16')`. Parameters: new (str|Tree): The new tree enviroment to compare old (str|Tree): The old tree environment to compare prepend_header (bool): If True, adds a header to the diff with release versions Returns: A dictionary of relevant changes between the two releases ''' dd = {'paths': {'new': {}, 'updated': {}}} if isinstance(new, six.string_types): new = Tree(config=new.lower()) if isinstance(old, six.string_types): old = Tree(config=old.lower()) new_templates = new.paths old_templates = old.paths # diffs = [] if prepend_header and 'releases' not in dd: new_name = new.environ['default']['name'] old_name = old.environ['default']['name'] dd['releases'] = {'new': new_name, 'old': old_name} unique_new = sorted(set(new_templates) - set(old_templates)) if unique_new: for path in unique_new: dd['paths']['new'][path] = new_templates[path] # changes changed = [] for name, template in new_templates.items(): if name in old_templates and template != old_templates[name]: changed.append((name, template, old_templates[name])) if changed: for item in changed: name, newt, oldt = item dd['paths']['updated'][name] = {'from': oldt, 'to': newt} return dd