1 |
commit: faa343b43fa644fddfac4f1fa8ab12e61b9107f7 |
2 |
Author: André Erdmann <dywi <AT> mailerd <DOT> de> |
3 |
AuthorDate: Mon Jan 27 14:40:41 2014 +0000 |
4 |
Commit: André Erdmann <dywi <AT> mailerd <DOT> de> |
5 |
CommitDate: Mon Jan 27 14:40:41 2014 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=faa343b4 |
7 |
|
8 |
move query_config code to roverlay/ |
9 |
|
10 |
--- |
11 |
bin/py/query_config.py | 345 +-------------------------- |
12 |
roverlay/scripts/__init__.py | 5 + |
13 |
{bin/py => roverlay/scripts}/query_config.py | 22 +- |
14 |
3 files changed, 20 insertions(+), 352 deletions(-) |
15 |
|
16 |
diff --git a/bin/py/query_config.py b/bin/py/query_config.py |
17 |
index bd13674..2905304 100644 |
18 |
--- a/bin/py/query_config.py |
19 |
+++ b/bin/py/query_config.py |
20 |
@@ -1,352 +1,17 @@ |
21 |
#!/usr/bin/python |
22 |
# -*- coding: utf-8 -*- |
23 |
# |
24 |
-# *** TODO: script name *** |
25 |
+# See roverlay.scripts.query_config for usage |
26 |
+# or simply run query_config.py --help. |
27 |
# |
28 |
-# Script for querying roverlay's config / editing template files. |
29 |
-# |
30 |
-# Usage: |
31 |
-# * query-config -h |
32 |
-# |
33 |
-# * query-config -l |
34 |
-# |
35 |
-# Lists all known config options. |
36 |
-# (Note: it's not possible to query all of these options) |
37 |
-# |
38 |
-# * query-config [-C <config_file>] [-u] [-a|{option[=varname]}] |
39 |
-# |
40 |
-# Prints roverlay's config options in shell usable format (without relying |
41 |
-# on roverlay-sh). Prints all options if -a/--all is specified or no |
42 |
-# option[=varname] is given. options can be renamed with "=varname". |
43 |
-# |
44 |
-# Usage example: |
45 |
-# |
46 |
-# $ eval $(query-config -C R-overlay.conf.tmp OVERLAY_DIR=OVERLAY OVERLAY_NAME) |
47 |
-# $ echo $OVERLAY |
48 |
-# $ echo $OVERLAY_NAME |
49 |
-# |
50 |
-# * query-config [-C <config_file>] [-u] -f <infile> [-O <outfile>|-] {-v VAR[=VALUE]} |
51 |
-# |
52 |
-# Replaces occurences of @@VARIABLES@@ in <infile> with values taken |
53 |
-# from roverlay's config and writes the result to <outfile> or stdout. |
54 |
-# (variables may also be specified with -v VAR=VALUE, which take precedence |
55 |
-# over roverlay's config, e.g. "-v SERVER_NAME=roverlay"). |
56 |
-# |
57 |
-# Usage example: |
58 |
-# |
59 |
-# $ query-config -C ~roverlay_user/roverlay/R-overlay.conf \ |
60 |
-# -f nginx.conf.in -O nginx.conf -v SERVER_ADDR=... -v SERVER_NAME=... |
61 |
-# |
62 |
-# A non-zero exit code indicates that one or more variables could not be |
63 |
-# replaced. |
64 |
-# |
65 |
-# |
66 |
-from __future__ import print_function, unicode_literals |
67 |
|
68 |
-import argparse |
69 |
-import logging |
70 |
-import re |
71 |
-import os |
72 |
import sys |
73 |
|
74 |
-import roverlay.core |
75 |
-import roverlay.strutil |
76 |
-from roverlay.config.entryutil import iter_config_keys |
77 |
- |
78 |
-EX_OK = os.EX_OK |
79 |
-EX_ERR = os.EX_OK^1 |
80 |
-EX_MISS = os.EX_OK^2 |
81 |
-EX_IRUPT = os.EX_OK^130 |
82 |
- |
83 |
-RE_VAR_REF = re.compile ( "@@([a-zA-Z_]+)@@" ) |
84 |
-RE_VARNAME = re.compile ( "^[a-zA-Z_]+$" ) |
85 |
- |
86 |
- |
87 |
-class VarnameArgumentError ( argparse.ArgumentTypeError ): |
88 |
- def __init__ ( self, name ): |
89 |
- super ( VarnameArgumentError, self ).__init__ ( |
90 |
- "invalid variable name: {!r}".format ( name ) |
91 |
- ) |
92 |
-# --- end of VarnameArgumentError --- |
93 |
- |
94 |
-def get_value_str ( value, list_join_seq=" " ): |
95 |
- if value is None: |
96 |
- return "" |
97 |
- elif hasattr ( value, '__iter__' ) and not isinstance ( value, str ): |
98 |
- return list_join_seq.join ( map ( str, value ) ) |
99 |
- elif isinstance ( value, bool ): |
100 |
- return "1" if value else "0" |
101 |
- else: |
102 |
- return str ( value ) |
103 |
-# --- end of get_value_str (...) --- |
104 |
- |
105 |
-def format_variables ( vardict, append_newline=True ): |
106 |
- retstr = "\n".join ( |
107 |
- "{varname!s}=\"{value!s}\"".format ( varname=k, value=v ) |
108 |
- for k, v in sorted ( vardict.items(), key=lambda kv: kv[0] ) |
109 |
- ) |
110 |
- return ( retstr + "\n" ) if append_newline else retstr |
111 |
-# --- end of format_variables (...) --- |
112 |
- |
113 |
-def get_parser(): |
114 |
- def arg_couldbe_file ( value ): |
115 |
- if value is None or value == '-': |
116 |
- return value |
117 |
- elif value: |
118 |
- f = os.path.abspath ( value ) |
119 |
- if not os.path.exists ( f ) or not os.path.isdir ( f ): |
120 |
- return f |
121 |
- raise argparse.ArgumentTypeError ( |
122 |
- "{!r} cannot be a file.".format ( value ) |
123 |
- ) |
124 |
- # --- end of arg_couldbe_file (...) --- |
125 |
- |
126 |
- def arg_is_filepath_or_none ( value ): |
127 |
- if value: |
128 |
- f = os.path.abspath ( value ) |
129 |
- if os.path.isfile ( f ): |
130 |
- return f |
131 |
- elif value is None: |
132 |
- return value |
133 |
- raise argparse.ArgumentTypeError ( |
134 |
- "{!r} is not a file.".format ( value ) |
135 |
- ) |
136 |
- # --- end of arg_is_filepath_or_none (...) --- |
137 |
- |
138 |
- def arg_is_varname ( value ): |
139 |
- if value: |
140 |
- vname, sepa, valias = value.partition ( '=' ) |
141 |
- if not RE_VARNAME.match ( vname ): |
142 |
- raise VarnameArgumentError ( vname ) |
143 |
- elif sepa: |
144 |
- if not RE_VARNAME.match ( valias ): |
145 |
- raise VarnameArgumentError ( valias ) |
146 |
- else: |
147 |
- return ( vname, valias ) |
148 |
- else: |
149 |
- return vname |
150 |
- #return ( vname, vname ) |
151 |
- else: |
152 |
- return None |
153 |
- # --- end of arg_is_varname (...) --- |
154 |
- |
155 |
- def arg_is_variable ( value ): |
156 |
- if value: |
157 |
- key, sepa, value = value.partition ( "=" ) |
158 |
- if sepa: |
159 |
- return ( key, roverlay.strutil.unquote ( value ) ) |
160 |
- else: |
161 |
- return ( key, "" ) |
162 |
- raise argparse.ArgumentTypeError ( value ) |
163 |
- # --- end of arg_is_variable (...) --- |
164 |
- |
165 |
- parser = argparse.ArgumentParser ( |
166 |
- description = ( |
167 |
- "query config options and output them in shell-usable format" |
168 |
- ), |
169 |
- epilog = ( |
170 |
- 'Exit codes:\n' |
171 |
- '* {EX_OK}: success\n' |
172 |
- '* {EX_ERR}: unspecified error, e.g. invalid config entry map\n' |
173 |
- '* {EX_MISS}: one or more config keys could not be found\n' |
174 |
- ).format ( EX_OK=EX_OK, EX_MISS=EX_MISS, EX_ERR=EX_ERR ), |
175 |
- formatter_class = argparse.RawDescriptionHelpFormatter |
176 |
- ) |
177 |
- |
178 |
- parser.add_argument ( |
179 |
- "config_keys", metavar="<config_key>", type=arg_is_varname, nargs="*", |
180 |
- help="config key (or <config_key>=<alias_key>)" |
181 |
- ) |
182 |
- |
183 |
- parser.add_argument ( |
184 |
- "-C", "--config-file", metavar="<file>", default=None, |
185 |
- type=arg_is_filepath_or_none, |
186 |
- help="path to the config file", |
187 |
- ) |
188 |
- |
189 |
- parser.add_argument ( |
190 |
- "-a", "--all", dest="print_all", default=False, action="store_true", |
191 |
- help="print all options" |
192 |
- ) |
193 |
- |
194 |
- parser.add_argument ( |
195 |
- "-l", "--list-all", dest="list_all", default=False, action="store_true", |
196 |
- help="instead of printing options: list all keys" |
197 |
- ) |
198 |
- |
199 |
- parser.add_argument ( |
200 |
- "-u", "--empty-missing", default=False, action="store_true", |
201 |
- help="set missing variables to the empty string" |
202 |
- ) |
203 |
- |
204 |
- parser.add_argument ( |
205 |
- "-f", "--from-file", metavar="<file>", default=None, |
206 |
- type=arg_is_filepath_or_none, |
207 |
- help="read config keys from <file>" |
208 |
- ) |
209 |
- |
210 |
- parser.add_argument ( |
211 |
- "-O", "--outfile", metavar="<file>", default=None, |
212 |
- type=arg_couldbe_file, |
213 |
- help=( |
214 |
- 'in conjunction with --from-file: replace variable references and ' |
215 |
- 'write the resulting text to <file>' |
216 |
- ) |
217 |
- ) |
218 |
- |
219 |
- parser.add_argument ( |
220 |
- "-v", "--variable", metavar="<key=\"value\">", dest="extra_vars", |
221 |
- default=[], action="append", type=arg_is_variable, |
222 |
- help="additional variables (only with --outfile)" |
223 |
- ) |
224 |
- |
225 |
- return parser |
226 |
-# --- end of get_parser (...) --- |
227 |
- |
228 |
-def get_all_config_keys(): |
229 |
- return [ k.upper() for k in iter_config_keys() ] |
230 |
-# --- end of get_all_config_keys (...) --- |
231 |
- |
232 |
-def get_vardict ( config, argv, keys ): |
233 |
- return config.query_by_name ( |
234 |
- keys, empty_missing=argv.empty_missing, convert_value=get_value_str |
235 |
- ) |
236 |
-# --- end of get_vardict (...) --- |
237 |
- |
238 |
-def main__print_variables ( config, argv, stream, config_keys ): |
239 |
- num_missing, cvars = get_vardict ( config, argv, config_keys ) |
240 |
- if cvars: |
241 |
- stream.write ( format_variables ( cvars ) ) |
242 |
- return num_missing |
243 |
-# --- end of main__print_variables (...) --- |
244 |
- |
245 |
-def main ( is_installed=False ): |
246 |
- parser = get_parser() |
247 |
- argv = parser.parse_args() |
248 |
- stream = sys.stdout |
249 |
- |
250 |
- # setup |
251 |
- ## logging |
252 |
- roverlay.core.force_console_logging ( log_level=logging.WARNING ) |
253 |
- |
254 |
- ## main config |
255 |
- if argv.config_file is None: |
256 |
- config_file = roverlay.core.locate_config_file ( False ) |
257 |
- else: |
258 |
- config_file = argv.config_file |
259 |
- |
260 |
- # passing installed=True|False doesn't really matter |
261 |
- config = roverlay.core.load_config_file ( |
262 |
- config_file, extraconf={ 'installed': is_installed, }, |
263 |
- setup_logger=False, load_main_only=True |
264 |
- ) |
265 |
- |
266 |
- # perform actions as requested |
267 |
- |
268 |
- # --list-all: print all config keys and exit |
269 |
- if argv.list_all: |
270 |
- stream.write ( "\n".join ( sorted ( get_all_config_keys() ) ) + "\n" ) |
271 |
- return EX_OK |
272 |
- |
273 |
- # --all or no config keys specified: print all config options as variables |
274 |
- elif argv.print_all or not any (( argv.from_file, argv.config_keys, )): |
275 |
- main__print_variables ( config, argv, stream, get_all_config_keys() ) |
276 |
- # don't return EX_MISS if --all was specified |
277 |
- return EX_OK |
278 |
- |
279 |
- # --from-file with --outfile: |
280 |
- # replace @@VARIABLES@@ in file and write to --outfile (or stdout) |
281 |
- elif argv.from_file and argv.outfile: |
282 |
- # COULDFIX: exit code when --variable is used |
283 |
- # |
284 |
- # (a) get_vardict(): return a list of missing vars and compare it |
285 |
- # to the final cvars |
286 |
- # (b) check the resulting str for missing vars (RE_VAR_REF.search) |
287 |
- # |
288 |
- # Using (b) for now (and unconditionally, so that the output |
289 |
- # always gets verified). |
290 |
- # |
291 |
- |
292 |
- # list of 2-tuples ( line, set<varnames> ) |
293 |
- input_lines = list() |
294 |
- config_keys = set() |
295 |
- with open ( argv.from_file, 'rt' ) as FH: |
296 |
- for line in FH.readlines(): |
297 |
- varnames = set ( RE_VAR_REF.findall ( line ) ) |
298 |
- input_lines.append ( ( line, varnames ) ) |
299 |
- config_keys |= varnames |
300 |
- # -- end for |
301 |
- # -- end with |
302 |
- |
303 |
- num_missing, cvars = get_vardict ( config, argv, config_keys ) |
304 |
- del num_missing |
305 |
- |
306 |
- if argv.extra_vars: |
307 |
- for k, v in argv.extra_vars: |
308 |
- cvars[k] = v |
309 |
- # -- end if extra vars |
310 |
- |
311 |
- # create a dict<varname => (regex for replacing varname,replacement)> |
312 |
- # where (re_object,replacement) := (re<@@varname@@>,value) |
313 |
- re_repl = { |
314 |
- k : ( re.compile ( "@@" + k + "@@" ), v ) for k, v in cvars.items() |
315 |
- } |
316 |
- |
317 |
- # iterate through input_lines a second time, replacing @@VARNAMES@@ |
318 |
- # (COULDFIX: could be done in one loop // create cvars on-the-fly (defaultdict etc)) |
319 |
- output_lines = [] |
320 |
- vars_missing = set() |
321 |
- for line, varnames in input_lines: |
322 |
- # apply replace operations as needed |
323 |
- for varname in varnames: |
324 |
- try: |
325 |
- re_obj, repl = re_repl [varname] |
326 |
- except KeyError: |
327 |
- # cannot replace varname |
328 |
- vars_missing.add ( varname ) |
329 |
- else: |
330 |
- line = re_obj.sub ( repl, line ) |
331 |
- # -- end for <varname // replace> |
332 |
- |
333 |
- output_lines.append ( line ) |
334 |
- # -- end for <input_lines> |
335 |
- |
336 |
- # write output_lines |
337 |
- if argv.outfile == '-': |
338 |
- stream.write ( ''.join ( output_lines ) ) |
339 |
- else: |
340 |
- with open ( argv.outfile, 'wt' ) as FH: |
341 |
- FH.write ( ''.join ( output_lines ) ) |
342 |
- # -- end write output_lines |
343 |
- |
344 |
- return EX_MISS if vars_missing else EX_OK |
345 |
- |
346 |
- # --from-file (without --outfile): read config keys from file |
347 |
- elif argv.from_file: |
348 |
- config_keys = set() |
349 |
- with open ( argv.from_file, 'rt' ) as FH: |
350 |
- for line in FH.readlines(): |
351 |
- config_keys.update ( RE_VAR_REF.findall ( line ) ) |
352 |
- # -- end with |
353 |
- |
354 |
- if main__print_variables ( config, argv, stream, config_keys ): |
355 |
- return EX_MISS |
356 |
- else: |
357 |
- return EX_OK |
358 |
- |
359 |
- # else filter out False/None values |
360 |
- elif main__print_variables ( |
361 |
- config, argv, stream, [ kx for kx in argv.config_keys if kx ] |
362 |
- ): |
363 |
- return EX_MISS |
364 |
- else: |
365 |
- return EX_OK |
366 |
- |
367 |
-# --- end of main (...) --- |
368 |
+import roverlay.scripts.query_config |
369 |
|
370 |
if __name__ == '__main__': |
371 |
try: |
372 |
- sys.exit ( main() ) |
373 |
+ sys.exit ( roverlay.scripts.query_config.query_config_main ( False ) ) |
374 |
except KeyboardInterrupt: |
375 |
- sys.exit ( EX_IRUPT ) |
376 |
+ sys.exit ( roverlay.scripts.query_config.EX_IRUPT ) |
377 |
# -- end __main__ |
378 |
|
379 |
diff --git a/roverlay/scripts/__init__.py b/roverlay/scripts/__init__.py |
380 |
new file mode 100644 |
381 |
index 0000000..664940b |
382 |
--- /dev/null |
383 |
+++ b/roverlay/scripts/__init__.py |
384 |
@@ -0,0 +1,5 @@ |
385 |
+# R overlay -- helper scripts package |
386 |
+# -*- coding: utf-8 -*- |
387 |
+# Copyright (C) 2014 André Erdmann <dywi@×××××××.de> |
388 |
+# Distributed under the terms of the GNU General Public License; |
389 |
+# either version 2 of the License, or (at your option) any later version. |
390 |
|
391 |
diff --git a/bin/py/query_config.py b/roverlay/scripts/query_config.py |
392 |
similarity index 96% |
393 |
copy from bin/py/query_config.py |
394 |
copy to roverlay/scripts/query_config.py |
395 |
index bd13674..f8a3c6f 100644 |
396 |
--- a/bin/py/query_config.py |
397 |
+++ b/roverlay/scripts/query_config.py |
398 |
@@ -1,7 +1,9 @@ |
399 |
-#!/usr/bin/python |
400 |
+# R overlay -- helper scripts package, query-config |
401 |
# -*- coding: utf-8 -*- |
402 |
+# Copyright (C) 2014 André Erdmann <dywi@×××××××.de> |
403 |
+# Distributed under the terms of the GNU General Public License; |
404 |
+# either version 2 of the License, or (at your option) any later version. |
405 |
# |
406 |
-# *** TODO: script name *** |
407 |
# |
408 |
# Script for querying roverlay's config / editing template files. |
409 |
# |
410 |
@@ -53,6 +55,9 @@ import roverlay.core |
411 |
import roverlay.strutil |
412 |
from roverlay.config.entryutil import iter_config_keys |
413 |
|
414 |
+__all__ = [ 'query_config_main', ] |
415 |
+ |
416 |
+ |
417 |
EX_OK = os.EX_OK |
418 |
EX_ERR = os.EX_OK^1 |
419 |
EX_MISS = os.EX_OK^2 |
420 |
@@ -220,7 +225,7 @@ def main__print_variables ( config, argv, stream, config_keys ): |
421 |
return num_missing |
422 |
# --- end of main__print_variables (...) --- |
423 |
|
424 |
-def main ( is_installed=False ): |
425 |
+def query_config_main ( is_installed ): |
426 |
parser = get_parser() |
427 |
argv = parser.parse_args() |
428 |
stream = sys.stdout |
429 |
@@ -231,7 +236,7 @@ def main ( is_installed=False ): |
430 |
|
431 |
## main config |
432 |
if argv.config_file is None: |
433 |
- config_file = roverlay.core.locate_config_file ( False ) |
434 |
+ config_file = roverlay.core.locate_config_file ( is_installed ) |
435 |
else: |
436 |
config_file = argv.config_file |
437 |
|
438 |
@@ -342,11 +347,4 @@ def main ( is_installed=False ): |
439 |
else: |
440 |
return EX_OK |
441 |
|
442 |
-# --- end of main (...) --- |
443 |
- |
444 |
-if __name__ == '__main__': |
445 |
- try: |
446 |
- sys.exit ( main() ) |
447 |
- except KeyboardInterrupt: |
448 |
- sys.exit ( EX_IRUPT ) |
449 |
-# -- end __main__ |
450 |
+# --- end of query_config_main (...) --- |