Mercurial > hgrepos > Python > libs > ConfigMix
comparison configmix/__init__.py @ 266:46571485b7d4
Allow loading configuration files from directories when using the "<dir>" prefix in filenames.
Unknown filetypes within these directories are ignored automatically.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Thu, 10 Sep 2020 02:00:11 +0200 |
| parents | 39c379fa8c65 |
| children | d715c10f2930 |
comparison
equal
deleted
inserted
replaced
| 265:39c379fa8c65 | 266:46571485b7d4 |
|---|---|
| 26 | 26 |
| 27 | 27 |
| 28 import fnmatch | 28 import fnmatch |
| 29 import copy | 29 import copy |
| 30 import io | 30 import io |
| 31 import os | |
| 31 import re | 32 import re |
| 32 | 33 |
| 33 from .compat import u, u2fs | 34 from .compat import u, u2fs |
| 34 from .config import Configuration | 35 from .config import Configuration |
| 35 | 36 |
| 68 if defaults is None: | 69 if defaults is None: |
| 69 ex = Configuration() | 70 ex = Configuration() |
| 70 else: | 71 else: |
| 71 ex = merge(None, Configuration(defaults)) | 72 ex = merge(None, Configuration(defaults)) |
| 72 for f in files: | 73 for f in files: |
| 73 nx = _load_cfg_from_file(f) | 74 if f.startswith("<dir>"): |
| 74 if nx is not None: | 75 for f2 in _get_configuration_files_from_dir(f[5:]): |
| 75 ex = merge(nx, ex) | 76 nx = _load_cfg_from_file(f2, ignore_unknown=True) |
| 77 if nx is not None: | |
| 78 ex = merge(nx, ex) | |
| 79 else: | |
| 80 nx = _load_cfg_from_file(f) | |
| 81 if nx is not None: | |
| 82 ex = merge(nx, ex) | |
| 76 if extras: | 83 if extras: |
| 77 ex = merge(Configuration(extras), ex) | 84 ex = merge(Configuration(extras), ex) |
| 78 return Configuration(ex) | 85 return Configuration(ex) |
| 79 | 86 |
| 80 | 87 |
| 88 if defaults is None: | 95 if defaults is None: |
| 89 ex = Configuration() | 96 ex = Configuration() |
| 90 else: | 97 else: |
| 91 ex = safe_merge(None, Configuration(defaults)) | 98 ex = safe_merge(None, Configuration(defaults)) |
| 92 for f in files: | 99 for f in files: |
| 93 nx = _load_cfg_from_file(f) | 100 if f.startswith("<dir>"): |
| 94 if nx is not None: | 101 for f2 in _get_configuration_files_from_dir(f[5:]): |
| 95 ex = safe_merge(nx, ex) | 102 nx = _load_cfg_from_file(f2, ignore_unknown=True) |
| 103 if nx is not None: | |
| 104 ex = safe_merge(nx, ex) | |
| 105 else: | |
| 106 nx = _load_cfg_from_file(f) | |
| 107 if nx is not None: | |
| 108 ex = safe_merge(nx, ex) | |
| 96 if extras: | 109 if extras: |
| 97 ex = safe_merge(Configuration(extras), ex) | 110 ex = safe_merge(Configuration(extras), ex) |
| 98 return Configuration(ex) | 111 return Configuration(ex) |
| 112 | |
| 113 | |
| 114 def _get_configuration_files_from_dir(root): | |
| 115 """Returns the sorted list of files within directory `root` | |
| 116 | |
| 117 """ | |
| 118 files = [] | |
| 119 | |
| 120 if not os.path.isdir(root): | |
| 121 return files | |
| 122 | |
| 123 dirfiles = os.listdir(root) | |
| 124 dirfiles.sort() | |
| 125 for f in dirfiles: | |
| 126 path = os.path.join(root, f) | |
| 127 if os.path.isdir(path): | |
| 128 # XXX TBD Recurse??? depth-first??? | |
| 129 continue | |
| 130 files.append(path) | |
| 131 return files | |
| 99 | 132 |
| 100 | 133 |
| 101 def _load_yaml(filename): | 134 def _load_yaml(filename): |
| 102 from . import yaml | 135 from . import yaml |
| 103 with open(u2fs(filename), "rb") as yf: | 136 with open(u2fs(filename), "rb") as yf: |
| 291 _extensions.append((fnpattern, mode)) | 324 _extensions.append((fnpattern, mode)) |
| 292 else: | 325 else: |
| 293 _extensions.insert(0, (fnpattern, mode)) | 326 _extensions.insert(0, (fnpattern, mode)) |
| 294 | 327 |
| 295 | 328 |
| 296 def _load_cfg_from_file(filename): | 329 def _load_cfg_from_file(filename, ignore_unknown=False): |
| 297 """Determine the loader for file `filename` and return the loaded | 330 """Determine the loader for file `filename` and return the loaded |
| 298 configuration dict. | 331 configuration dict. |
| 332 | |
| 333 If `ignore_unknown` is `True` then unknown extensions are ignored. | |
| 334 Otherwise a :exc:`ValueError` exception is raised. | |
| 299 | 335 |
| 300 Can return `None` is the file should be ignored by the caller. | 336 Can return `None` is the file should be ignored by the caller. |
| 301 | 337 |
| 302 """ | 338 """ |
| 303 for p, m in _extensions: | 339 for p, m in _extensions: |
| 306 m = m(filename) | 342 m = m(filename) |
| 307 if m is None: | 343 if m is None: |
| 308 continue | 344 continue |
| 309 return mode_loaders[m](filename) | 345 return mode_loaders[m](filename) |
| 310 else: | 346 else: |
| 311 raise ValueError("Unknown configuration file type for filename " | 347 if ignore_unknown: |
| 312 "%r" % filename) | 348 return None |
| 349 else: | |
| 350 raise ValueError("Unknown configuration file type for filename " | |
| 351 "%r" % filename) | |
| 313 | 352 |
| 314 | 353 |
| 315 if 0: | 354 if 0: |
| 316 # | 355 # |
| 317 # From: https://github.com/jet9/python-yconfig/blob/master/yconfig.py | 356 # From: https://github.com/jet9/python-yconfig/blob/master/yconfig.py |
