1 |
4 |
danv |
#!/usr/bin/env python3
|
2 |
|
|
###############################################################################
|
3 |
|
|
#
|
4 |
|
|
# Copyright (C) 2014-2018
|
5 |
|
|
# ASTRON (Netherlands Institute for Radio Astronomy)
|
6 |
|
|
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
|
7 |
|
|
#
|
8 |
|
|
# This program is free software: you can redistribute it and/or modify
|
9 |
|
|
# it under the terms of the GNU General Public License as published by
|
10 |
|
|
# the Free Software Foundation, either version 3 of the License, or
|
11 |
|
|
# (at your option) any later version.
|
12 |
|
|
#
|
13 |
|
|
# This program is distributed in the hope that it will be useful,
|
14 |
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
|
|
# GNU General Public License for more details.
|
17 |
|
|
#
|
18 |
|
|
# You should have received a copy of the GNU General Public License
|
19 |
|
|
# along with this program. If not, see .
|
20 |
|
|
#
|
21 |
|
|
# $Id: configfile_modifier.py 18609 2018-07-18 08:06:30Z overeem $
|
22 |
|
|
#
|
23 |
|
|
###############################################################################
|
24 |
|
|
|
25 |
|
|
"""
|
26 |
|
|
Interactive program to modify all configfiles found in the hierarchical directory
|
27 |
|
|
structure under the given top directory.
|
28 |
|
|
"""
|
29 |
|
|
|
30 |
|
|
from argparse import ArgumentParser
|
31 |
|
|
from hdl_raw_access import RawConfigTree
|
32 |
|
|
|
33 |
|
|
# Define a simple menu system that is based on a dict that contains the menu actions:
|
34 |
|
|
# the keys are the valid strings the user may enter
|
35 |
|
|
# the values are lists: the first element is the menu tekst, the second the function to call and
|
36 |
|
|
# the remaining elememts (if any) are the arguments to ask the user
|
37 |
|
|
# All arguments are stored in a kwargs structure and passed to the functions that is called.
|
38 |
|
|
|
39 |
|
|
|
40 |
|
|
def get_menu_choice(menu, title):
|
41 |
|
|
"""
|
42 |
|
|
Iterate over the menu dict, show the menu choices and ask for input till valid input is received.
|
43 |
|
|
"""
|
44 |
|
|
print("\n", title)
|
45 |
|
|
print("-" * len(title))
|
46 |
|
|
input_ok = False
|
47 |
|
|
while not input_ok:
|
48 |
|
|
for key in sorted(menu.keys()):
|
49 |
|
|
print("{} {}".format(key, menu[key][0]))
|
50 |
|
|
choice = input("\n >>: ")
|
51 |
|
|
if choice not in list(menu.keys()):
|
52 |
|
|
print("ERROR: This input is not a valid menu choice. Try again.")
|
53 |
|
|
else:
|
54 |
|
|
input_ok = True
|
55 |
|
|
return menu[choice]
|
56 |
|
|
|
57 |
|
|
|
58 |
|
|
def execute_menu_line(line_spec, verbose):
|
59 |
|
|
"""
|
60 |
|
|
Given a menu line specification it asks the user for the specified arguments, stores the values in a
|
61 |
|
|
kwargs structure and finally call the specified function with this kwargs.
|
62 |
|
|
"""
|
63 |
|
|
print("\n--- {} ---".format(line_spec[0]))
|
64 |
|
|
nr_args = len(line_spec) - 2
|
65 |
|
|
if nr_args < 0:
|
66 |
|
|
raise SyntaxError("Invalid formatted menuline definition: {}.\nNeed at least two items in the list".format(line_spec))
|
67 |
|
|
if nr_args == 0:
|
68 |
|
|
return line_spec[1]()
|
69 |
|
|
# Iterate over the remaining items and get values for them
|
70 |
|
|
kwargs = {"verbose": verbose}
|
71 |
|
|
for spec_idx in range(2, len(line_spec)):
|
72 |
|
|
answer = input(line_spec[spec_idx].capitalize().replace("_", " ") + ": ")
|
73 |
|
|
kwargs[line_spec[spec_idx]] = answer
|
74 |
|
|
line_spec[1](**kwargs)
|
75 |
|
|
|
76 |
|
|
|
77 |
|
|
# ## Implementation of the menu commands
|
78 |
|
|
# Note: cleaner would to implement this with the Strategy pattern but we want to keep the code
|
79 |
|
|
# to be readable for everyone. ;-)
|
80 |
|
|
def change_value_of_key(**kwargs):
|
81 |
|
|
key = kwargs.pop("key")
|
82 |
|
|
new_value = kwargs.pop("new_value")
|
83 |
|
|
verbose = kwargs.pop("verbose")
|
84 |
|
|
global tree
|
85 |
|
|
for filename in sorted(tree.configfiles.keys()):
|
86 |
|
|
tree.configfiles[filename].change_value(key, new_value, verbose)
|
87 |
|
|
|
88 |
|
|
|
89 |
|
|
def append_key_value(**kwargs):
|
90 |
|
|
key = kwargs.pop("new_key")
|
91 |
|
|
new_value = kwargs.pop("new_value")
|
92 |
|
|
verbose = kwargs.pop("verbose")
|
93 |
|
|
global tree
|
94 |
|
|
for filename in sorted(tree.configfiles.keys()):
|
95 |
|
|
tree.configfiles[filename].append_key_value(key, new_value, verbose)
|
96 |
|
|
|
97 |
|
|
|
98 |
|
|
def insert_key_at_linenr(**kwargs):
|
99 |
|
|
new_key = kwargs.pop("new_key")
|
100 |
|
|
new_value = kwargs.pop("new_value")
|
101 |
|
|
linenumber = int(kwargs.pop("linenumber"))
|
102 |
|
|
verbose = kwargs.pop("verbose")
|
103 |
|
|
global tree
|
104 |
|
|
for filename in sorted(tree.configfiles.keys()):
|
105 |
|
|
tree.configfiles[filename].insert_key_at_linenr(new_key, new_value, linenumber, verbose)
|
106 |
|
|
|
107 |
|
|
|
108 |
|
|
def insert_key_value_before_key(**kwargs):
|
109 |
|
|
new_key = kwargs.pop("new_key")
|
110 |
|
|
new_value = kwargs.pop("new_value")
|
111 |
|
|
before_key = kwargs.pop("before_key")
|
112 |
|
|
verbose = kwargs.pop("verbose")
|
113 |
|
|
global tree
|
114 |
|
|
for filename in sorted(tree.configfiles.keys()):
|
115 |
|
|
tree.configfiles[filename].insert_key_value_before_key(new_key, new_value, before_key, verbose)
|
116 |
|
|
|
117 |
|
|
|
118 |
|
|
def rename_key(**kwargs):
|
119 |
|
|
old_key = kwargs.pop("old_key")
|
120 |
|
|
new_key = kwargs.pop("new_key")
|
121 |
|
|
verbose = kwargs.pop("verbose")
|
122 |
|
|
global tree
|
123 |
|
|
for filename in sorted(tree.configfiles.keys()):
|
124 |
|
|
tree.configfiles[filename].rename_key(old_key, new_key, verbose)
|
125 |
|
|
|
126 |
|
|
|
127 |
|
|
def remove_key(**kwargs):
|
128 |
|
|
key = kwargs.pop("key")
|
129 |
|
|
verbose = kwargs.pop("verbose")
|
130 |
|
|
global tree
|
131 |
|
|
for filename in sorted(tree.configfiles.keys()):
|
132 |
|
|
tree.configfiles[filename].remove_key(key, verbose)
|
133 |
|
|
|
134 |
|
|
|
135 |
|
|
def end_menu():
|
136 |
|
|
global running
|
137 |
|
|
running = False
|
138 |
|
|
|
139 |
|
|
|
140 |
|
|
if __name__ == '__main__':
|
141 |
|
|
# setup parser and parse the arguments.
|
142 |
|
|
argparser = ArgumentParser(description='Options and arguments for modifying collections of configfiles.')
|
143 |
|
|
argparser.add_argument('filename', help="Filename like 'hdl_buildset_.cfg'")
|
144 |
|
|
argparser.add_argument('rootdir', help="Top directory to start the search for configfiles.")
|
145 |
|
|
argparser.add_argument('-v', '--verbose', help="Show more information on what happens.", action="store_true")
|
146 |
|
|
args = argparser.parse_args()
|
147 |
|
|
|
148 |
|
|
tree = RawConfigTree(args.rootdir, args.filename)
|
149 |
|
|
print("Found {} configfiles in {}".format(len(tree.configfiles), args.rootdir))
|
150 |
|
|
if args.verbose:
|
151 |
|
|
for filename in sorted(tree.configfiles.keys()):
|
152 |
|
|
print(filename)
|
153 |
|
|
|
154 |
|
|
# define the menu including actions
|
155 |
|
|
# choice choice description function to call arguments to ask for
|
156 |
|
|
menu = {'1': ["Change value", change_value_of_key, "key", "new_value"],
|
157 |
|
|
'2': ["Append key", append_key_value, "new_key", "new_value"],
|
158 |
|
|
'3': ["Insert key at linenr", insert_key_at_linenr, "new_key", "new_value", "linenumber"],
|
159 |
|
|
'4': ["Insert key before other key", insert_key_value_before_key, "new_key", "new_value", "before_key"],
|
160 |
|
|
'5': ["Rename key", rename_key, "old_key", "new_key"],
|
161 |
|
|
'6': ["Remove key", remove_key, "key"],
|
162 |
|
|
'q': ["Exit", end_menu]
|
163 |
|
|
}
|
164 |
|
|
|
165 |
|
|
running = True
|
166 |
|
|
while running:
|
167 |
|
|
execute_menu_line(get_menu_choice(menu, "Menu for changing multiple configfiles"), args.verbose)
|
168 |
|
|
|