comparison configmix/__init__.py @ 178:eeb3ed104ea1

Begin refactoring the associations between filename extensions and loader functions: Make is indirect via the file mode.
author Franz Glasner <fzglas.hg@dom66.de>
date Thu, 02 May 2019 09:42:28 +0200
parents 6dde1e344ae8
children 62db35db8939
comparison
equal deleted inserted replaced
177:6dde1e344ae8 178:eeb3ed104ea1
114 def _load_ini(filename): 114 def _load_ini(filename):
115 from . import ini 115 from . import ini
116 return ini.load(filename) 116 return ini.load(filename)
117 117
118 118
119 _default_loaders = [ 119 DEFAULT_MODE_LOADERS = {
120 ("*.yml", _load_yaml), 120 "python": _load_py,
121 ("*.yaml", _load_yaml), 121 "yaml": _load_yaml,
122 ("*.json", _load_json), 122 "conf": _load_ini,
123 ("*.py", _load_py), 123 "conf-windows": _load_ini,
124 ("*.ini", _load_ini), 124 "ini": _load_ini,
125 "javascript": _load_json,
126 "json": _load_json,
127 }
128 """Default associations between file modes and loader functions"""
129
130
131 DEFAULT_EXTENSIONS = [
132 ("*.yml", "yaml"),
133 ("*.yaml", "yaml"),
134 ("*.json", "json"),
135 ("*.py", "python"),
136 ("*.ini", "conf"),
125 ] 137 ]
126 """The builtin default associations of extensions with loaders -- in that 138 """The builtin default associations of filename extensions with
127 order 139 file modes -- in that order.
140
141 The "mode" part may be a string or a callable with a filename
142 parameter that returns the mode string for the file or `None` if it
143 can not determined.
128 144
129 """ 145 """
130 146
131 147
132 DEFAULT_LOADER = object() 148 DEFAULT_LOADER = object()
146 return loader 162 return loader
147 else: 163 else:
148 raise KeyError("No loader for pattern %r" % pattern) 164 raise KeyError("No loader for pattern %r" % pattern)
149 165
150 166
151 _loaders = [] 167 _mode_loaders = {}
152 """All configured loader functions""" 168 """All configured associations between file modes and loader functions.
169
170 See :data:`DEFAULT_MODE_LOADERS.
171
172 """
173
174 _extensions = []
175 """All configured assiciations of filename extensions with file modes.
176
177 See :data:`DEFAULT_EXTENSIONS`
178
179 """
153 180
154 181
155 def clear_loader(): 182 def clear_loader():
156 """Remove all configured loader associations. 183 """Remove all configured loader associations.
157 184
172 return loader 199 return loader
173 else: 200 else:
174 raise KeyError("No loader for pattern %r" % pattern) 201 raise KeyError("No loader for pattern %r" % pattern)
175 202
176 203
177 def set_loader(fnpattern, loader): 204 def set_loader(fnpattern, mode):
178 """Associate a :mod:`fnmatch` style pattern `fnpattern` with a 205 """Associate a :mod:`fnmatch` style pattern `fnpattern` with a file
179 callable `loader` that will be called when :func:`load` encounters 206 mode `mode` that determines what will be called when :func:`load`
180 a file argument that matches `fnpattern`. 207 encounters a file argument that matches `fnpattern`.
181 208
182 :param str fnpattern: the :mod:`fnmatch` pattern to associate a loader with 209 :param str fnpattern: the :mod:`fnmatch` pattern to associate a loader with
183 :param callable loader: a callable that accepts a `filename` argument and 210 :param callable mode: a mode string or a callable that accepts a
184 returns a parsed configuration from a given file 211 `filename` argument and returns a file
212 mode for the given file (or `None`)
185 213
186 This function prepends to the given pattern to the currently defined 214 This function prepends to the given pattern to the currently defined
187 associations. 215 associations.
188 216
189 The OS specific case-sensitivity behaviour of 217 The OS specific case-sensitivity behaviour of
192 220
193 If `loader` is :data:`DEFAULT_LOADER` then the default association 221 If `loader` is :data:`DEFAULT_LOADER` then the default association
194 from :data:`_default_loaders` will be used -- if any. 222 from :data:`_default_loaders` will be used -- if any.
195 223
196 """ 224 """
197 if loader is DEFAULT_LOADER: 225 if mode is DEFAULT_LOADER:
198 for _p, _l in _default_loaders: 226 for p, m in DEFAULT_EXTENSIONS:
199 if _p == fnpattern: 227 if p == fnpattern:
200 _loaders.insert(0, (fnpattern, _l)) 228 _extensions.insert(0, (fnpattern, m))
201 break 229 break
202 else: 230 else:
203 raise ValueError("no DEFAULT loader for pattern: %r" % fnpattern) 231 raise ValueError("no DEFAULT mode for pattern: %r" % fnpattern)
204 else: 232 else:
205 _loaders.insert(0, (fnpattern, loader)) 233 _extensions.insert(0, (fnpattern, mode))
206 234
207 235
208 def _load_cfg_from_file(filename): 236 def _load_cfg_from_file(filename):
209 for _p, _l in _loaders: 237 for p, m in _extensions:
210 if fnmatch.fnmatch(filename, _p): 238 if fnmatch.fnmatch(filename, p):
211 return _l(filename) 239 if callable(m):
240 m = m(filename)
241 if m is None:
242 continue
243 return _mode_loaders[m](filename)
212 else: 244 else:
213 raise ValueError("Unknown configuration file type for filename " 245 raise ValueError("Unknown configuration file type for filename "
214 "%r" % filename) 246 "%r" % filename)
215 247
216 248
356 return True 388 return True
357 return False 389 return False
358 390
359 391
360 # 392 #
361 # Init loader defaults 393 # Init loader defaults: mode->loader and extension->mode
362 # 394 #
363 for _pattern, _ld in _default_loaders: 395 _mode_loaders.update(DEFAULT_MODE_LOADERS)
364 set_loader(_pattern, _ld) 396 for _pattern, _mode in DEFAULT_EXTENSIONS:
397 set_loader(_pattern, _mode)