diff options
| author | John Estabrook <jestabro@vyos.io> | 2026-05-07 12:42:14 -0500 |
|---|---|---|
| committer | John Estabrook <jestabro@vyos.io> | 2026-05-07 13:55:16 -0500 |
| commit | e514f728cd48478e88543f6e9e5c6c9423b8e0df (patch) | |
| tree | 7382571106691c466df8c1889f10a318ca00cf04 /scripts | |
| parent | 88d5f4a80e57c22c7fe8ff9c67090d295478ca68 (diff) | |
| download | vyos-1x-e514f728cd48478e88543f6e9e5c6c9423b8e0df.tar.gz vyos-1x-e514f728cd48478e88543f6e9e5c6c9423b8e0df.zip | |
T8360: add XML preprocessor to allow overriding help element
Diffstat (limited to 'scripts')
| -rwxr-xr-x | scripts/override-help | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/scripts/override-help b/scripts/override-help new file mode 100755 index 000000000..16c74bbed --- /dev/null +++ b/scripts/override-help @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +# +# Copyright (C) VyOS Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# + +# Use lxml xpath capability to find multiple elements with tag help +# relative to path; copy and replace to override the initial value. + +import sys +import glob +import logging +from copy import deepcopy +from lxml import etree + +debug = False + +logger = logging.getLogger(__name__) +logs_handler = logging.StreamHandler() +logger.addHandler(logs_handler) + +if debug: + logger.setLevel(logging.DEBUG) +else: + logger.setLevel(logging.INFO) + + +def override_element(lst: list): + """ + Allow multiple override elements; use the final one (in document order). + """ + if len(lst) < 2: + logger.debug('passing list of single element to override_element') + return + + # replace element with final override + first_element = lst[0] + # lxml will remove on replace, hence make a copy to avoid cleaning up + # empty elements + final_element = deepcopy(lst[-1]) + parent = first_element.getparent() + parent.replace(first_element, final_element) + + +def collect_and_override(dir_name): + # pylint: disable=too-many-locals,c-extension-no-member + """ + Collect elements with help tag into dictionary indexed by name + attributes of ancestor path. + """ + for fname in glob.glob(f'{dir_name}/*.xml'): + tree = etree.parse(fname) + root = tree.getroot() + defv = {} + + xpath_str = '//help' + xp = tree.xpath(xpath_str) + + for element in xp: + ap = element.xpath('ancestor::*[@name]') + ap_name = [el.get('name') for el in ap] + ap_path_str = ' '.join(ap_name) + defv.setdefault(ap_path_str, []).append(element) + + trivial = [] + for k, v in defv.items(): + if len(v) < 2: + trivial.append(k) + for i in trivial: + del defv[i] + + for k, v in defv.items(): + text_set = set() + for e in v: + text_set.add(e.text) + if len(text_set) > 1: + logger.debug(f'Inconsistent help elements in file {fname}:') + for e in v: + logger.debug( + f'Element is {e.tag} with content {e.text} at {e.sourceline}' + ) + + logger.info(f"overriding help in path '{k}'") + override_element(v) + + revised_str = etree.tostring(root, encoding='unicode', pretty_print=True) + + with open(f'{fname}', 'w') as f: + f.write(revised_str) + + +def main(): + if len(sys.argv) < 2: + logger.critical('Must specify XML directory!') + sys.exit(1) + + dir_name = sys.argv[1] + + collect_and_override(dir_name) + + +if __name__ == '__main__': + main() |
