Gentoo Archives: gentoo-commits

From: "André Erdmann" <dywi@×××××××.de>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/R_overlay:master commit in: roverlay/scripts/, bin/py/
Date: Mon, 27 Jan 2014 14:47:05
Message-Id: 1390833641.faa343b43fa644fddfac4f1fa8ab12e61b9107f7.dywi@gentoo
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 (...) ---