Skip to content

Instantly share code, notes, and snippets.

@sulrich
Created July 28, 2025 17:50
Show Gist options
  • Select an option

  • Save sulrich/6c6d58531fa42f3f9db0706dca865ae3 to your computer and use it in GitHub Desktop.

Select an option

Save sulrich/6c6d58531fa42f3f9db0706dca865ae3 to your computer and use it in GitHub Desktop.
compare-paths.py
#!/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