Mercurial > hgrepos > Python > libs > ConfigMix
comparison docs/introduction.rst @ 215:ab3d0326419c
Doc: Move the "doc" to "docs"
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Wed, 08 May 2019 09:23:37 +0200 |
| parents | doc/introduction.rst@fa660f084ceb |
| children | 57ff12610dc5 |
comparison
equal
deleted
inserted
replaced
| 214:a35b0ca8b81f | 215:ab3d0326419c |
|---|---|
| 1 .. -*- coding: utf-8; indent-tabs-mode: nil; -*- | |
| 2 | |
| 3 .. _introduction: | |
| 4 | |
| 5 Introduction | |
| 6 ============ | |
| 7 | |
| 8 .. contents:: | |
| 9 :local: | |
| 10 | |
| 11 The configurations can be read from different types of files: | |
| 12 | |
| 13 - :ref:`YAML files <yaml-files>` | |
| 14 - :ref:`JSON files <json-files>` | |
| 15 - :ref:`INI files <ini-files>` | |
| 16 - :ref:`TOML files <toml-files>` | |
| 17 - :ref:`executable Python scripts <executable-python-scripts>` | |
| 18 | |
| 19 | |
| 20 .. _yaml-files: | |
| 21 | |
| 22 YAML Files | |
| 23 ---------- | |
| 24 | |
| 25 Need the :mod:`yaml` package (https://github.com/yaml/pyyaml) | |
| 26 (e.g. ``pip install pyyaml``) | |
| 27 | |
| 28 .. note:: All strings are returned as Unicode text strings. | |
| 29 | |
| 30 .. note:: The root object must be a *mapping* and therefore decode | |
| 31 into a Python :class:`dict` alike. This is checked by the | |
| 32 implementation. | |
| 33 | |
| 34 An example is: | |
| 35 | |
| 36 .. literalinclude:: ../tests/data/conf10.yml | |
| 37 :language: yaml | |
| 38 | |
| 39 | |
| 40 .. _json-files: | |
| 41 | |
| 42 JSON files | |
| 43 ---------- | |
| 44 | |
| 45 Read the JSON file with the help of Python's native :mod:`json` package. | |
| 46 | |
| 47 .. note:: All strings are returned as Unicode text strings. | |
| 48 | |
| 49 .. note:: The root object must be an *object* and therefore decode | |
| 50 into a Python :class:`dict` alike. This is checked by the | |
| 51 implementation. | |
| 52 | |
| 53 An example is: | |
| 54 | |
| 55 .. literalinclude:: ../tests/data/conf10.json | |
| 56 :language: js | |
| 57 | |
| 58 For comments in JSON files see section :ref:`comments`. | |
| 59 | |
| 60 | |
| 61 .. _ini-files: | |
| 62 | |
| 63 INI Files | |
| 64 --------- | |
| 65 | |
| 66 Read the file and all sections named in parameter `extract` are flattened | |
| 67 into the resulting dictionary. By default the section named ``config`` is | |
| 68 used. | |
| 69 | |
| 70 Normally all values are returned as Unicode text strings. | |
| 71 But values can be annotated and therefore interpreted as other types: | |
| 72 | |
| 73 ``:int:`` | |
| 74 The value is handled in the same way as a Python :class:`int` | |
| 75 literal | |
| 76 | |
| 77 ``:float:`` | |
| 78 The value is interpreted as :class:`float` | |
| 79 | |
| 80 ``:bool:`` | |
| 81 The resulting value is a :class:`bool` where | |
| 82 | |
| 83 ``1``, ``true``, ``yes``, ``on`` | |
| 84 yield a Python ``True`` | |
| 85 | |
| 86 ``0``, ``false``, ``no``, ``off`` | |
| 87 yield a Python ``False`` | |
| 88 | |
| 89 The evaluation is done *case-insensitively*. | |
| 90 | |
| 91 .. note:: All strings are returned as Unicode text strings. | |
| 92 | |
| 93 .. note:: Contrary to the behaviour of the standard Python :mod:`configparser` | |
| 94 module the INI file reader is *case-sensitive*. | |
| 95 | |
| 96 The example INI style configuration below yields an equivalent | |
| 97 configuration to the YAML configuration above: | |
| 98 | |
| 99 .. literalinclude:: ../tests/data/conf10.ini | |
| 100 :language: ini | |
| 101 | |
| 102 As can be seen in this example -- INI file internal value interpolation | |
| 103 is done as in Python's standard :mod:`configparser` module. | |
| 104 | |
| 105 This example also illustrates how INI sections are used to build a | |
| 106 tree-ish configuration dictionary. | |
| 107 | |
| 108 | |
| 109 .. _toml-files: | |
| 110 | |
| 111 TOML Files | |
| 112 ---------- | |
| 113 | |
| 114 Read the TOML file with the help of the pure Python :mod:`toml` | |
| 115 package (https://github.com/uiri/toml) (e.g. ``pip install toml``). | |
| 116 | |
| 117 All TOML features map seamingless to "ConfigMix". | |
| 118 | |
| 119 The example TOML style configuration below yields an equivalent | |
| 120 configuration to the YAML configuration above: | |
| 121 | |
| 122 | |
| 123 .. literalinclude:: ../tests/data/conf10.toml | |
| 124 :language: ini | |
| 125 | |
| 126 | |
| 127 .. _executable-python-scripts: | |
| 128 | |
| 129 Executable Python Scripts | |
| 130 ------------------------- | |
| 131 | |
| 132 What will be exported: | |
| 133 | |
| 134 1. If loading is done with the `extract` parameter only the given keys are | |
| 135 extracted from the script. | |
| 136 | |
| 137 2. Otherwise it is checked if the scripts defines an ``__all__`` | |
| 138 sequence. If there is one it's contents are the keys to be | |
| 139 extracted. | |
| 140 | |
| 141 3. If there is no ``__all__`` object all names not starting with an | |
| 142 underscore ``_`` are found. | |
| 143 | |
| 144 This is analogous to as Python modules behave when importing them with | |
| 145 ``from module import *``. | |
| 146 | |
| 147 .. note:: The Python configuration files are evaluated with ``exec`` and not | |
| 148 imported. | |
| 149 | |
| 150 The example configuration by Python script below yields an equivalent | |
| 151 configuration to the YAML configuration above: | |
| 152 | |
| 153 .. literalinclude:: ../tests/data/conf10.py | |
| 154 :language: python | |
| 155 | |
| 156 | |
| 157 .. _loading-and-merging: | |
| 158 | |
| 159 Loading and Merging | |
| 160 ------------------- | |
| 161 | |
| 162 Basic usage of the API is as follows in this example:: | |
| 163 | |
| 164 import configmix | |
| 165 | |
| 166 # | |
| 167 # Note: With conf10 merging is rather pointless because the tree | |
| 168 # files # are really the same configuration. But is doesn't harm | |
| 169 # also here. | |
| 170 # | |
| 171 config = configmix.load("conf10.yml", "conf10.ini", "conf10.py") | |
| 172 | |
| 173 # Get a -- possibly interpolated -- configuration variable's value | |
| 174 value1 = config.getvar_s("key1") | |
| 175 | |
| 176 # Get a -- possibly interpolated -- variable from within the tree | |
| 177 value2 = config.getvar_s("tree1.tree2.key4") | |
| 178 | |
| 179 | |
| 180 By default filenames of the configuration files must have the extensions | |
| 181 (case-sensitivety depends on your OS): | |
| 182 | |
| 183 ``.ini`` | |
| 184 for INI configuration files | |
| 185 | |
| 186 ``.json`` | |
| 187 for JSON configuration files | |
| 188 | |
| 189 ``.py`` | |
| 190 for Python configuration files | |
| 191 | |
| 192 ``.toml`` | |
| 193 for TOML configuration file | |
| 194 | |
| 195 ``.yml`` or ``.yaml`` | |
| 196 for YAML configuration files | |
| 197 | |
| 198 | |
| 199 .. _getting-values: | |
| 200 | |
| 201 Getting configuration variables | |
| 202 ------------------------------- | |
| 203 | |
| 204 Get a -- possibly interpolated -- configuration variable's value with:: | |
| 205 | |
| 206 value1 = config.getvar_s("key1") | |
| 207 | |
| 208 Get a raw configuration variable's value with:: | |
| 209 | |
| 210 value1_raw = config.getvar("key1") | |
| 211 | |
| 212 Because the configuration is not only a plain list of but a tree of | |
| 213 key-value pairs you will want to fetch them by separating the individual | |
| 214 level keys with a point ``.``. | |
| 215 | |
| 216 Looking at the example in chapter :ref:`yaml-files` -- when calling | |
| 217 ``config.getvar_s("tree1.tree2.key4")`` you will get the value | |
| 218 ``get this as `tree1.tree2.key4'``. | |
| 219 | |
| 220 This is true for both methods :py:meth:`.Configuration.getvar` and | |
| 221 :py:meth:`.Configuration.getvar_s`. | |
| 222 | |
| 223 Both methods also perform :ref:`variable-interpolation` and handle | |
| 224 :ref:`variable-namespaces`. Filtering is not supported. So -- the | |
| 225 variable name arguments of :py:meth:`.Configuration.getvar` and | |
| 226 :py:meth:`.Configuration.getvar_s` are of the form | |
| 227 ``[namespace:]variable``. | |
| 228 | |
| 229 | |
| 230 .. _comments: | |
| 231 | |
| 232 Comments | |
| 233 -------- | |
| 234 | |
| 235 By default all keys beginning with ``__comment`` or ``__doc`` are | |
| 236 filtered out and not given to the application. This allows comments in | |
| 237 JSON files -- but is not restricted to JSON files only. | |
| 238 | |
| 239 For all types of configuration files their respective standard comments | |
| 240 are allowed too. | |
| 241 | |
| 242 | |
| 243 .. _variable-namespaces: | |
| 244 | |
| 245 Variable Namespaces | |
| 246 ------------------- | |
| 247 | |
| 248 Currently there are 4 namespaces: | |
| 249 | |
| 250 1. The unnamed namespace (which is also default). | |
| 251 | |
| 252 All the configuration variables are part of this namespace. | |
| 253 | |
| 254 2. The namespace ``OS`` | |
| 255 | |
| 256 Available functions: | |
| 257 | |
| 258 ``cwd`` | |
| 259 Contains the current working directory of the process | |
| 260 | |
| 261 3. The namespace ``ENV`` | |
| 262 | |
| 263 This namespace contains all the environment variables as they are | |
| 264 available from :py:data:`os.environ`. | |
| 265 | |
| 266 4. The namespace ``PY`` | |
| 267 | |
| 268 Contains selected values from the running Python: | |
| 269 | |
| 270 ``version`` | |
| 271 The return value of :py:func:`platform.python_version` | |
| 272 | |
| 273 ``version_maj_min`` | |
| 274 Just the major and minor version of the running Python | |
| 275 (``.`` separated) | |
| 276 | |
| 277 ``version_maj`` | |
| 278 Just the major version of the running Python | |
| 279 | |
| 280 ``implementation`` | |
| 281 The return value of :py:func:`platform.python_implementation` | |
| 282 | |
| 283 | |
| 284 Examples | |
| 285 ~~~~~~~~ | |
| 286 | |
| 287 :: | |
| 288 | |
| 289 config.getvar("OS:cwd") | |
| 290 | |
| 291 yields the current working directory as :py:func:`os.getcwd` does. | |
| 292 | |
| 293 | |
| 294 .. _variable-interpolation: | |
| 295 | |
| 296 Variable Interpolation | |
| 297 ---------------------- | |
| 298 | |
| 299 Configuration variable values that are read with | |
| 300 :py:meth:`.Configuration.getvar_s` are subject to variable | |
| 301 interpolation. The general syntactic pattern for this is:: | |
| 302 | |
| 303 {{[namespace:]variable[|filter[|filter...]]}} | |
| 304 | |
| 305 I.e.: between double curly braces an optional `namespace` name followed by | |
| 306 a colon ``:``, the `variable` and then zero or more filters, each one | |
| 307 introduced by a pipe symbol ``|``. | |
| 308 | |
| 309 Variables are expanded *lately* at runtime -- exactly when calling | |
| 310 :py:meth:`.Configuration.getvar_s`, | |
| 311 :py:meth:`.Configuration.substitute_variables_in_obj` or | |
| 312 :py:meth:`.Configuration.expand_variable` | |
| 313 | |
| 314 | |
| 315 Filter functions | |
| 316 ~~~~~~~~~~~~~~~~ | |
| 317 | |
| 318 Interpolated values can be processed through a series of filter functions:: | |
| 319 | |
| 320 {{my.variable|filter1|filter2}} | |
| 321 | |
| 322 Available filter functions are: | |
| 323 | |
| 324 ``urlquote`` | |
| 325 | |
| 326 ``saslprep`` | |
| 327 | |
| 328 ``normpath`` | |
| 329 | |
| 330 ``abspath`` | |
| 331 | |
| 332 ``posixpath`` | |
| 333 | |
| 334 ``lower`` | |
| 335 | |
| 336 ``upper`` | |
| 337 | |
| 338 | |
| 339 Examples | |
| 340 ~~~~~~~~ | |
| 341 | |
| 342 :: | |
| 343 | |
| 344 {{OS:cwd|posixpath}} | |
| 345 | |
| 346 expands to the current working directory as POSIX path: on Windows all | |
| 347 backslashes are replaced by forward slashes. | |
| 348 | |
| 349 :: | |
| 350 | |
| 351 {{ENV:PATH}} | |
| 352 | |
| 353 expands to the current search path from the process environment. | |
| 354 | |
| 355 :: | |
| 356 | |
| 357 {{PY:version}} | |
| 358 | |
| 359 expands to the current running Python version (e.g. ``3.6.4``). | |
| 360 | |
| 361 :: | |
| 362 | |
| 363 {{PY::implementation|upper}} | |
| 364 | |
| 365 expands to something like ``CPYTHON`` when using the standard Python | |
| 366 interpreter written in C. | |
| 367 | |
| 368 | |
| 369 Custom filename extensions and custom loaders | |
| 370 --------------------------------------------- | |
| 371 | |
| 372 If you want to have custom configuration file extensions and/or custom loaders | |
| 373 for custom configuration files you have various possibilities: | |
| 374 | |
| 375 Associate an additional new extension (e.g. ".conf") with an | |
| 376 existing configuration file style (e.g. YAML):: | |
| 377 | |
| 378 configmix.set_assoc("*.conf", configmix.get_assoc("*.yml")) | |
| 379 | |
| 380 Allow only files with extension ".cfg" in INI-style -- using the default | |
| 381 loader for INI-files:: | |
| 382 | |
| 383 configmix.clear_assoc() | |
| 384 configmix.set_assoc("*.cfg", configmix.get_default_assoc("*.ini")) | |
| 385 | |
| 386 Only a new configuration file style:: | |
| 387 | |
| 388 def my_custom_loader(filename): | |
| 389 ... | |
| 390 return some_dict_alike | |
| 391 | |
| 392 configmix.mode_loaders["myconfmode"] = my_custom_loader | |
| 393 configmix.clear_assoc() | |
| 394 configmix.set_assoc("*.my.configuration", "myconfmode") | |
| 395 | |
| 396 If :py:func:`~configmix.clear_assoc` will not be called then just a *new* | |
| 397 configuration file style will be installed. | |
| 398 | |
| 399 To select the loader not by extension but by an Emacs-compatible mode | |
| 400 declaration (e.g. ``mode: yaml``) in the first two lines of a file use:: | |
| 401 | |
| 402 configmix.set_assoc("*", configmix.try_determine_filemode) |
