Created
July 28, 2025 17:50
-
-
Save sulrich/6c6d58531fa42f3f9db0706dca865ae3 to your computer and use it in GitHub Desktop.
compare-paths.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # given the following items: | |
| # - a master list of openconfig paths (--master-list) | |
| # - a list of paths which will be compared against the master list (--target-list) | |
| # | |
| # output the following: | |
| # - a list of paths which are requested in the target-list but are | |
| # not supported in the master path list (missing paths) | |
| # - a list of paths which exist in both lists (supported paths) | |
| # | |
| # the master_list must contain the following fields in the output. | |
| # - path | |
| # - support_status | |
| # - augment | |
| # - notes | |
| import argparse | |
| import csv | |
| import re | |
| import sys | |
| def parse_cli_args(): | |
| """parse command line options and CLI flag dependencies. | |
| parameters: none | |
| returns: | |
| type: argparse object""" | |
| parser = argparse.ArgumentParser(usage=arg_usage()) | |
| parser.add_argument( | |
| "--master-list", | |
| dest="master_list", | |
| help="path to a master list of supported openconfig paths", | |
| required=True, | |
| ) | |
| parser.add_argument( | |
| "--target-list", | |
| dest="target_list", | |
| help="path to a csv file of paths which are to be compared against the master list", | |
| required=True, | |
| ) | |
| parser.add_argument( | |
| "--missing-paths", | |
| dest="missing_paths", | |
| help="dump a list of the paths which are missing from the target list", | |
| required=False, | |
| action="store_true", | |
| ) | |
| parser.add_argument( | |
| "--known-paths", | |
| dest="known_paths", | |
| help="dump a list of the paths from the target list which are known in the master list", | |
| required=False, | |
| action="store_true", | |
| ) | |
| parser.add_argument( | |
| "--csv-out", | |
| dest="csv_out", | |
| help="dump a sorted list of the target paths with the state of the support available in a separate field", | |
| required=False, | |
| action="store_true", | |
| ) | |
| args = parser.parse_args() | |
| if not (args.known_paths or args.csv_out or args.missing_paths): | |
| print("\nERROR: you must pick an output format") | |
| print(arg_usage()) | |
| sys.exit() | |
| return args | |
| def load_master_paths(csv_file): | |
| """load csv file and return the contents of the path column w/scrubbed | |
| appropriately. | |
| parameters: | |
| csv_file(string): path to the CSV file to load | |
| returns: | |
| - paths(list): a list containing the paths in the CSV file. all with a | |
| leading '/' and/or necessary cleanup. | |
| - path_state(dict of dicts) - keyed by the scrubbed path. | |
| - path: (key) | |
| - support_status: "string", | |
| - augment: "string", | |
| - notes: "string" | |
| """ | |
| paths = [] | |
| path_info = {} # nested dict with support info | |
| try: | |
| with open(csv_file, newline="") as path_file: | |
| import_reader = csv.DictReader(path_file) | |
| for row in import_reader: | |
| if row["path"] == "": # skip blank lines | |
| continue | |
| # check to make sure that we have a root to our path | |
| if not re.match(r"^\/", row["path"]): | |
| row["path"] = "/" + row["path"] | |
| item_dict = { | |
| "support_status": row["support_status"], | |
| "augment": row["augment"], | |
| "notes": row["notes"], | |
| } | |
| paths.append(row["path"]) | |
| path_info[row["path"]] = item_dict | |
| except IOError: | |
| print("error opening csv_file file:", csv_file) | |
| sys.exit() | |
| return paths, path_info | |
| def load_target_paths(csv_file): | |
| """load csv file and return the contents of the path column w/scrubbed appropriately. | |
| parameters: | |
| csv_file(string): path to the CSV file to load | |
| returns: | |
| - paths(list): a list containing the paths in the CSV file. all with a | |
| leading '/' and/or necessary cleanup. | |
| """ | |
| paths = [] | |
| try: | |
| with open(csv_file, newline="") as path_file: | |
| import_reader = csv.DictReader(path_file) | |
| for row in import_reader: | |
| if row["path"] == "": # skip blank lines | |
| continue | |
| # check to make sure that we have a root to our path | |
| if not re.match(r"^\/", row["path"]): | |
| row["path"] = "/" + row["path"] | |
| paths.append(row["path"]) | |
| except IOError: | |
| print("error opening csv_file file:", csv_file) | |
| sys.exit() | |
| return paths | |
| def main(): | |
| opts = parse_cli_args() | |
| master_list, path_info = load_master_paths(opts.master_list) | |
| target_list = load_target_paths(opts.target_list) | |
| # items in the target list which are not in the master list | |
| if opts.missing_paths: | |
| missing_paths = set(target_list) - set(master_list) | |
| print("missing path(s) count:", len(missing_paths)) | |
| for p in sorted(missing_paths): | |
| print(p) | |
| if opts.known_paths: | |
| known_paths = set(target_list) & set(master_list) | |
| print("known path(s) count:", len(known_paths)) | |
| for q in sorted(known_paths): | |
| print(q, ",", path_info[q]["support_status"], sep="") | |
| # dump the comma separated list of paths | |
| if opts.csv_out: | |
| print("path,support_status") | |
| # resist the urge to sort this list, | |
| for path in target_list: | |
| if path in master_list: | |
| print(path, ",", path_info[path]["support_status"], sep="") | |
| else: | |
| print(path, ",", "not-supported", sep="") | |
| def arg_usage(): | |
| """output a reasonble usage message | |
| parameters: none | |
| returns: | |
| string: usage message""" | |
| return """ | |
| compare-paths.py --master-list=master.csv --target-list=target.csv | |
| --master-list - the path to a csv containing the master list of known | |
| openconfig paths in the EOS build you're working with | |
| --target-list - the path to a csv containing the list of openconfig paths for | |
| comparison against the master list. | |
| OUTPUT FORMATS (pick one): | |
| --missing-paths - output a list of paths from the target-list which are *not* | |
| referenceed in the master-list. | |
| --known-paths - output a list of paths from the target-list which are known in | |
| the master-list. | |
| --csv-out - output a CSV list of paths from the target-list with the state of | |
| support in the appropriate field. (dumps to STDOUT) | |
| """ | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment