From 109326f33999e03f3005d7927ce2f25ed537a1d5 Mon Sep 17 00:00:00 2001 From: Emily Boudreaux Date: Sun, 23 Feb 2025 11:29:16 -0500 Subject: [PATCH] feat(defaultConfig): added default config generation script While writing 4DSSE we want a way to keep track of what defaults have been set for config files, and validate that we are using the same config variables where we want to. This python script generates a "default" yaml file based on the default values given in .get --- utils/defaultConfig/defaults.yaml | 11 +++ utils/defaultConfig/generateDefaultConfig.py | 70 ++++++++++++++++++++ utils/defaultConfig/generateDefaultConfig.sh | 9 +++ utils/defaultConfig/readme.md | 14 ++++ 4 files changed, 104 insertions(+) create mode 100644 utils/defaultConfig/defaults.yaml create mode 100644 utils/defaultConfig/generateDefaultConfig.py create mode 100755 utils/defaultConfig/generateDefaultConfig.sh create mode 100644 utils/defaultConfig/readme.md diff --git a/utils/defaultConfig/defaults.yaml b/utils/defaultConfig/defaults.yaml new file mode 100644 index 0000000..6065fee --- /dev/null +++ b/utils/defaultConfig/defaults.yaml @@ -0,0 +1,11 @@ +opac: + lowTemp: + numeric: + maxIter: 10 +Probe: + GLVis: + Visualization: true + Host: localhost + Port: '19916' + LogManager: + DefaultLogName: 4DSSE.log diff --git a/utils/defaultConfig/generateDefaultConfig.py b/utils/defaultConfig/generateDefaultConfig.py new file mode 100644 index 0000000..9f7bb33 --- /dev/null +++ b/utils/defaultConfig/generateDefaultConfig.py @@ -0,0 +1,70 @@ +import os +import re +import yaml + +# Regular expression to match .get("a:b:c", x) +pattern = re.compile(r'\.get<([^>]+)>\("([^"]+)",\s*([^);]+)\)') + +def parse_value(value, type_hint): + """Converts values to appropriate types.""" + value = value.strip() + + # Handle common types + if type_hint in {"int", "long"}: + return int(value) + elif type_hint in {"float", "double"}: + return float(value) + elif type_hint == "bool": + return value.lower() in {"true", "1"} + elif value.startswith('"') and value.endswith('"'): + return value.strip('"') # Remove quotes for string literals + elif value.startswith("'") and value.endswith("'"): + return value.strip("'") # Remove single quotes + + return value # Return as-is if unsure + +def insert_into_dict(hierarchy_dict, keys, value, type_hint): + """Recursively inserts values into a nested dictionary.""" + key = keys.pop(0) + if not keys: # If last key, store value + hierarchy_dict[key] = parse_value(value, type_hint) + else: + if key not in hierarchy_dict: + hierarchy_dict[key] = {} + insert_into_dict(hierarchy_dict[key], keys, value, type_hint) + +def scan_files(directory): + """Scans all .cpp, .h, .c, and .hpp files in a directory recursively.""" + hierarchy_dict = {} + + for root, _, files in os.walk(directory): + for file in files: + if file.endswith(('.cpp', '.h', '.c', '.hpp')): + file_path = os.path.join(root, file) + with open(file_path, 'r', encoding='utf-8', errors='ignore') as f: + for line in f: + match = pattern.search(line) + if match: + type_hint, hierarchy, value = match.groups() + keys = hierarchy.split(":") + insert_into_dict(hierarchy_dict, keys, value, type_hint) + + return hierarchy_dict + +def save_yaml(data, output_file): + """Saves the nested dictionary to a YAML file.""" + with open(output_file, 'w', encoding='utf-8') as f: + yaml.dump(data, f, default_flow_style=False, sort_keys=False, indent=4) + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser(description="Generate a YAML file with default configuration values.") + parser.add_argument("directory", help="Directory to scan for .cpp, .h, .c, and .hpp files.") + parser.add_argument("-o", "--output", help="Output file name.", default="defaults.yaml") + args = parser.parse_args() + + extracted_data = scan_files(args.directory) + save_yaml(extracted_data, args.output) + + print(f"✅ YAML file generated: {args.output}") + diff --git a/utils/defaultConfig/generateDefaultConfig.sh b/utils/defaultConfig/generateDefaultConfig.sh new file mode 100755 index 0000000..16d9887 --- /dev/null +++ b/utils/defaultConfig/generateDefaultConfig.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Check if python is installed +if ! [ -x "$(command -v python)" ]; then + echo 'Error: python is not installed.' >&2 + exit 1 +fi + +python ./generateDefaultConfig.py ../../src \ No newline at end of file diff --git a/utils/defaultConfig/readme.md b/utils/defaultConfig/readme.md new file mode 100644 index 0000000..c25b38a --- /dev/null +++ b/utils/defaultConfig/readme.md @@ -0,0 +1,14 @@ +# Default Configuration Generator +Small tool to quickly generate a YAML config file which encodes all the default options used in 4DSSE. All c, c++, h, and hpp in the src directory are scanned and the config variables and their default values pulled out. + +## Usage +- You must have python installed + +```bash +./generateDefaultConfig.sh +``` + +There should now be a file called defaults.yaml which stores all the default values. + +## Notes +This file could be used as a config file; however, it is more realistically intended for debugging and for checking what the default values set for config options in the code are. \ No newline at end of file