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/config/
Date: Sun, 26 Jan 2014 19:07:03
Message-Id: 1390754264.d72284c4978f84bbdcdc54ce0c4b4d66b6d91ad3.dywi@gentoo
1 commit: d72284c4978f84bbdcdc54ce0c4b4d66b6d91ad3
2 Author: André Erdmann <dywi <AT> mailerd <DOT> de>
3 AuthorDate: Sun Jan 26 16:37:44 2014 +0000
4 Commit: André Erdmann <dywi <AT> mailerd <DOT> de>
5 CommitDate: Sun Jan 26 16:37:44 2014 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=d72284c4
7
8 roverlay/config/, ConfigTree: get options by name
9
10 Added get_by_name() to the ConfigTree, which is similar to get(), but takes an
11 option name (used in config files, e.g. OVERLAY_DIR) instead of a config path
12 (used in the code, e.g. ['OVERLAY','dir']) as key.
13 query_by_name() can be used to get multiple options and return them as dict.
14
15 Might be useful for scripting.
16
17 ---
18 roverlay/config/entryutil.py | 43 +++++++++++++++-----
19 roverlay/config/exceptions.py | 40 +++++++++++++++++++
20 roverlay/config/tree.py | 92 ++++++++++++++++++++++++++++++++++++++++---
21 3 files changed, 159 insertions(+), 16 deletions(-)
22
23 diff --git a/roverlay/config/entryutil.py b/roverlay/config/entryutil.py
24 index cd5f230..716c166 100644
25 --- a/roverlay/config/entryutil.py
26 +++ b/roverlay/config/entryutil.py
27 @@ -1,6 +1,6 @@
28 # R overlay -- config package, entryutil
29 # -*- coding: utf-8 -*-
30 -# Copyright (C) 2012 André Erdmann <dywi@×××××××.de>
31 +# Copyright (C) 2012-2014 André Erdmann <dywi@×××××××.de>
32 # Distributed under the terms of the GNU General Public License;
33 # either version 2 of the License, or (at your option) any later version.
34
35 @@ -11,9 +11,11 @@ __all__ = [ 'list_entries', ]
36 import re
37 import textwrap
38
39 +import roverlay.config.exceptions
40 from roverlay.config.entrymap import CONFIG_ENTRY_MAP
41
42 def deref_entry ( name ):
43 + # COULDFIX: raise ConfigOptionNotFound
44 entry_name = name.lower()
45 entry_next = CONFIG_ENTRY_MAP [entry_name]
46 while isinstance ( entry_next, str ):
47 @@ -25,29 +27,50 @@ def deref_entry ( name ):
48 def deref_entry_safe ( name ):
49 visited = set()
50 entry_name = name.lower()
51 - entry_next = CONFIG_ENTRY_MAP [entry_name]
52 + try:
53 + entry_next = CONFIG_ENTRY_MAP [entry_name]
54 + except KeyError:
55 + # entry does not exist
56 + raise roverlay.config.exceptions.ConfigOptionNotFound ( name )
57
58 while isinstance ( entry_next, str ):
59 visited.add ( entry_name )
60 entry_name = entry_next
61 - entry_next = CONFIG_ENTRY_MAP [entry_name]
62 + try:
63 + entry_next = CONFIG_ENTRY_MAP [entry_name]
64 + except KeyError:
65 + raise roverlay.config.exceptions.ConfigEntryMapException (
66 + "dangling config map entry {!r} (<- {!r})".format (
67 + entry_name, name
68 + )
69 + )
70
71 if entry_name in visited:
72 - raise Exception (
73 - "cyclic config entry detected for {!r}!".format ( name )
74 - )
75 + raise roverlay.config.exceptions.ConfigEntryMapException (
76 + "cyclic config entry detected for {!r}!".format ( name )
77 + )
78
79 return ( entry_name, entry_next )
80 # --- end of deref_entry_safe (...) ---
81
82 def find_config_path ( name ):
83 entry_name, entry = deref_entry_safe ( name )
84 - try:
85 - return entry ['path']
86 - except KeyError:
87 - return entry_name.split ( '_' )
88 + if entry:
89 + try:
90 + return entry ['path']
91 + except KeyError:
92 + return entry_name.split ( '_' )
93 + else:
94 + # hidden entry
95 + raise roverlay.config.exceptions.ConfigOptionNotFound ( name )
96 # --- end of find_config_path (...) ---
97
98 +def iter_config_keys():
99 + for key, entry in CONFIG_ENTRY_MAP.items():
100 + if isinstance ( entry, dict ):
101 + yield key
102 +# --- end of iter_config_keys (...) ---
103 +
104 def _iter_entries():
105 """Iterates through all entries in CONFIG_ENTRY_MAP and yields config
106 entry information (entry name, description).
107
108 diff --git a/roverlay/config/exceptions.py b/roverlay/config/exceptions.py
109 new file mode 100644
110 index 0000000..715d9eb
111 --- /dev/null
112 +++ b/roverlay/config/exceptions.py
113 @@ -0,0 +1,40 @@
114 +# R overlay -- config package, exceptions
115 +# -*- coding: utf-8 -*-
116 +# Copyright (C) 2014 André Erdmann <dywi@×××××××.de>
117 +# Distributed under the terms of the GNU General Public License;
118 +# either version 2 of the License, or (at your option) any later version.
119 +
120 +__all__ = [
121 + 'ConfigException', 'ConfigEntryMapException',
122 + 'ConfigKeyError', 'ConfigOptionNotFound',
123 + 'ConfigTreeUsageError',
124 +]
125 +
126 +
127 +class ConfigException ( Exception ):
128 + pass
129 +# --- end of ConfigException ---
130 +
131 +class ConfigEntryMapException ( ConfigException ):
132 + pass
133 +# --- end of ConfigEntryMapException ---
134 +
135 +
136 +class ConfigKeyError ( ConfigException ):
137 + # or inherit KeyError
138 + def __init__ ( self, config_key ):
139 + super ( ConfigKeyError, self ).__init__ (
140 + "config key {!r} not found but required.".format ( config_key )
141 + )
142 +# --- end of ConfigKeyError ---
143 +
144 +class ConfigOptionNotFound ( ConfigException ):
145 + pass
146 +# --- end of ConfigOptionNotFound ---
147 +
148 +class ConfigTreeUsageError ( ConfigException ):
149 + def __init__ ( self, message=None ):
150 + super ( ConfigTreeUsageError, self ).__init__ (
151 + "bad usage" if message is None else message
152 + )
153 +# --- end of ConfigTreeUsageError ---
154
155 diff --git a/roverlay/config/tree.py b/roverlay/config/tree.py
156 index d9f1900..0aeb86c 100644
157 --- a/roverlay/config/tree.py
158 +++ b/roverlay/config/tree.py
159 @@ -1,6 +1,6 @@
160 # R overlay -- config package, tree
161 # -*- coding: utf-8 -*-
162 -# Copyright (C) 2012 André Erdmann <dywi@×××××××.de>
163 +# Copyright (C) 2012-2014 André Erdmann <dywi@×××××××.de>
164 # Distributed under the terms of the GNU General Public License;
165 # either version 2 of the License, or (at your option) any later version.
166
167 @@ -20,9 +20,11 @@ __all__ = [ 'ConfigTree', ]
168
169 import logging
170
171 -from roverlay.config import const
172 -from roverlay.config.loader import ConfigLoader
173 -from roverlay.config.util import get_config_path
174 +import roverlay.config.exceptions
175 +from roverlay.config import const
176 +from roverlay.config.loader import ConfigLoader
177 +from roverlay.config.util import get_config_path
178 +from roverlay.config.entryutil import find_config_path
179
180 CONFIG_INJECTION_IS_BAD = True
181
182 @@ -115,7 +117,7 @@ class ConfigTree ( object ):
183 pass
184
185 else:
186 - raise Exception ( "bad usage" )
187 + raise roverlay.config.exceptions.ConfigUsageError()
188
189 # --- end of merge_with (...) ---
190
191 @@ -207,6 +209,9 @@ class ConfigTree ( object ):
192 * key --
193 * fallback_value --
194 * fail_if_unset -- fail if key is neither in config nor const
195 +
196 + raises:
197 + * ConfigKeyError -- key does not exist and fail_if_unset is True
198 """
199
200 config_value = self._findpath ( key )
201 @@ -219,7 +224,7 @@ class ConfigTree ( object ):
202 config_value = fallback
203
204 if config_value is None and fail_if_unset:
205 - raise Exception ( "config key '%s' not found but required." % key )
206 + raise roverlay.config.exceptions.ConfigKeyError ( key )
207
208 return config_value
209
210 @@ -230,6 +235,81 @@ class ConfigTree ( object ):
211 return self.get ( key, fail_if_unset=True )
212 # --- end of get_or_fail ---
213
214 + def get_by_name ( self, option_name, *args, **kwargs ):
215 + """Searches for an option referenced by name (e.g. OVERLAY_DIR)
216 + and returns its value. See ConfigTree.get() for details.
217 +
218 + This is an inefficient operation meant for setup/query scripts.
219 + Use get() where possible.
220 +
221 + arguments:
222 + * option_name
223 + * *args, **kwargs -- passed to get()
224 +
225 + raises:
226 + * ConfigOptionNotFound -- option_name is unknown or hidden
227 + * ConfigEntryMapException -- config entry is broken
228 + * ConfigKeyError -- key does not exist and fail_if_unset is True
229 + """
230 + return self.get ( find_config_path ( option_name ), *args, **kwargs )
231 + # --- end of get_by_name (...) ---
232 +
233 + def get_by_name_or_fail ( self, option_name ):
234 + """Alias to self.get_by_name ( key, fail_if_unset=True )."""
235 + return self.get_by_name ( option_name, fail_if_unset=True )
236 + # --- end of get_by_name_or_fail (...) ---
237 +
238 + def query_by_name ( self,
239 + request, empty_missing=False, convert_value=None
240 + ):
241 + """Creates a dict<var_name,value> of config options, referenced by name
242 +
243 + Returns: 2-tuple ( # of missing options, var dict ).
244 +
245 + arguments:
246 + * request -- an iterable containing strings
247 + or 2-tuples(option_name,var_name)
248 + * empty_missing -- whether to create empty entries for missing options
249 + or not. Defaults to False.
250 + * convert_value -- if set and not None: convert config values using
251 + this function before adding them to the resulting
252 + dict
253 + """
254 + num_missing = 0
255 + retvars = dict()
256 +
257 + for k in request:
258 + if (
259 + not isinstance ( k, str ) and hasattr ( k, '__iter__' )
260 + and len ( k ) > 1
261 + ):
262 +
263 + option_name = k[0]
264 + var_name = k[1]
265 + else:
266 + option_name = str(k)
267 + var_name = option_name
268 + # -- end if <set option_name/var_name>
269 +
270 + try:
271 + value = self.get_by_name_or_fail ( option_name )
272 + except (
273 + roverlay.config.exceptions.ConfigOptionNotFound,
274 + roverlay.config.exceptions.ConfigKeyError
275 + ):
276 + num_missing += 1
277 + if empty_missing:
278 + retvars [var_name] = ""
279 + else:
280 + if convert_value is not None:
281 + retvars [var_name] = convert_value ( value )
282 + else:
283 + retvars [var_name] = value
284 + # -- end for <request>
285 +
286 + return ( num_missing, retvars )
287 + # --- end of query_by_name (...) ---
288 +
289 def get_field_definition ( self, force_update=False ):
290 """Gets the field definition stored in this ConfigTree.