Source code for esm_parser.shell_to_dict

"""
Backwards compatability for old runscripts
"""
# Python 2 and 3 version agnostic compatiability:
from __future__ import print_function
from __future__ import unicode_literals
from __future__ import division
from __future__ import absolute_import

# Python Standard Library imports
import logging
import os
import sys
import subprocess

# Third party imports
import six

# Imports from this module
from .yaml_to_dict import *


from esm_rcfile import FUNCTION_PATH


[docs]def mini_recursive_run_func(config, func): func(config) for key, value in six.iteritems(config): if isinstance(value, dict): if not key == "export_vars": mini_recursive_run_func(value, func)
# NOTE: Both of the next to blocks need to be recursive through the whole dictionary... # # BLOCK 1: Use mapping table # Load a mapping table if it exists and swap old and new keys
[docs]def remap_old_new_keys(config): try: mapping_table_old_to_new = "not a thing yet" mapping_table = yaml_file_to_dict(mapping_table_old_to_new) for script_key, python_key in six.iteritems(mapping_table): for config_key, config_value in six.iteritems(config): if config_key == script_key: del config[script_key] config[python_key] = config_calue except: pass
# BLOCK 2: make every key lowercase always # # Adapt cases to always be lowercase (I guess this is the new default)
[docs]def purify_cases(config): import time purify_case = True if purify_case: keys = list(config) for key in keys: # value in six.iteritems(config): value = config[key] del config[key] new_key = key.lower() config[new_key] = value time.sleep(0.01)
[docs]def ShellscriptToUserConfig(runscript_path): """ Generates a User Config from an old Shellscript """ with open(runscript_path) as runscript_file: all_lines = runscript_file.readlines() hashbang = all_lines[0] bad_lines = ("load_all_functions", "general_do_it_all", "#", "set ") good_lines = [ line.strip() for line in all_lines if not line.startswith(bad_lines) ] good_lines.insert(0, hashbang) good_lines.insert(1, "set -a") # Module commands: module_commands = [line for line in good_lines if "module" in line] # Find index of a command "module purge" if "module purge" in module_commands: # Anything before module purge is probably irrelevant, so flip the # list around first before figuring out which index it is: index = module_commands[::-1].index("module purge") remaining_module_commands = module_commands[::-1][:index][::-1] else: remaining_module_commands = module_commands module_commands = [l for l in remaining_module_commands if "list" not in l] for module_command in module_commands: os.system(module_command) env_before = dict(os.environ) # the next lines remove functions all_keys = list(env_before.keys()) for key in all_keys: if "()" in key: del env_before[key] good_lines.append("unset -f " + key.replace("()","").replace("BASH_FUNC_", "")) logging.debug("Got environment from the system %s", env_before) with open("cleaned_runscript", "w") as cleaned_runscript: for line in good_lines: cleaned_runscript.write(line + "\n") logging.debug("Finished writing cleaned_runscript") command_to_run = "source %s/cleaned_runscript; env" % os.getcwd() logging.debug( "Using the following command to determine environment in runscript: %s", command_to_run, ) pipe1 = subprocess.Popen(command_to_run, stdout=subprocess.PIPE, shell=True) output = pipe1.communicate()[0].decode("utf-8") logging.debug(output) env_after = {} for line in output.split("\n"): if line and "=" in line: key, value = line.split("=", 1) if "()" not in key: if value: env_after[key] = value os.remove("cleaned_runscript") diffs = list(set(env_after) - set(env_before)) known_setups_and_models = os.listdir(FUNCTION_PATH) user_config = {} logging.debug(diffs) solved_diffs = [] for thisdiff in diffs: logging.debug("thisdiff=%s", thisdiff) for sim_thing in known_setups_and_models: diff_name = thisdiff.replace("_" + sim_thing, "").replace( sim_thing + "_", "" ) user_config.setdefault(sim_thing, {}) if thisdiff.endswith(sim_thing): user_config[sim_thing][diff_name] = env_after[thisdiff] solved_diffs.append(thisdiff) break if thisdiff.startswith(sim_thing): user_config[sim_thing][diff_name] = env_after[thisdiff] solved_diffs.append(thisdiff) break for k, v in six.iteritems(user_config): if v: user_config[k] = v for solved_diff in solved_diffs: diffs.remove(solved_diff) solved_diffs = [] deprecated_diffs = [ "FUNCTION_PATH", "FPATH", "machine_name", "ESM_USE_C_CALENDAR", ] user_config["general"] = {} for diff in diffs: if diff in deprecated_diffs: logging.warning( "You used a discontinued variable: %s.", diff, ) if diff not in deprecated_diffs: user_config["general"][diff] = env_after[diff] solved_diffs.append(diff) for solved_diff in solved_diffs: diffs.remove(solved_diff) logging.debug("Diffs after removing: %s", diffs) # Remove all empty dictionaries: for key in list(user_config): value = user_config[key] if not value: del user_config[key] # mini_recursive_run_func(user_config, remap_old_new_keys) mini_recursive_run_func(user_config, purify_cases) return user_config