From c378b28f4601fc32e023d443baaac8bb23fc9326 Mon Sep 17 00:00:00 2001 From: Mattijs Ugen <144798+akaIDIOT@users.noreply.github.com> Date: Fri, 11 Mar 2022 15:33:02 +0100 Subject: [PATCH 01/12] Add docs session to noxfile --- noxfile.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/noxfile.py b/noxfile.py index e88d2e3..1de23f0 100644 --- a/noxfile.py +++ b/noxfile.py @@ -47,6 +47,14 @@ def update(session): session.run('pip-compile', '--upgrade', '--no-header', '--no-emit-index-url', '--pip-args', f'--python-version {oldest_python}', '--output-file', 'test-requirements.txt', 'test-requirements.in') +@nox.session(python=newest_python) +def docs(session): + session.install('-r', 'requirements.txt') + session.install('sphinx', 'sphinx-rtd-theme') + + session.run('sphinx-build', '-b', 'html', 'docs/', 'dist/docs/') + + @nox.session(python=oldest_python) def dist(session): session.install('wheel') From 536bcbcffd1450ddbe10b60abd274209a1f01534 Mon Sep 17 00:00:00 2001 From: Mattijs Ugen <144798+akaIDIOT@users.noreply.github.com> Date: Fri, 11 Mar 2022 16:19:38 +0100 Subject: [PATCH 02/12] Add fail-fast TODO to use.rst --- docs/use.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/use.rst b/docs/use.rst index 87cbaf4..1a59ee2 100644 --- a/docs/use.rst +++ b/docs/use.rst @@ -4,6 +4,7 @@ How to use confidence - loading files - loading by name - creating `.Configuration` objects manually +- fail-fast: missing Logging ------- From 41025b374dc3de702e97c84aa96aba6a122f89cc Mon Sep 17 00:00:00 2001 From: Mattijs Ugen <144798+akaIDIOT@users.noreply.github.com> Date: Fri, 11 Mar 2022 16:21:29 +0100 Subject: [PATCH 03/12] Add a better lead-in to the docs root --- docs/index.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 9741869..ffaccef 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,7 +1,11 @@ Configure with confidence ========================= -``confidence`` helps loading configuration options from file into a user-friendly object at runtime. +Confidence helps loading configuration options from file into a user-friendly object at runtime. +Inspired by the way Python's own ``pip`` reads its configuration (try ``pip config debug`` if you're not familiar with ``pip``'s configuration), +confidence uses a similarly flexible, but deterministic approach to combining information from multiple configuration files. +If that sounds awfully complicated, there's no requirement that you need to use anything that feels complicated. +See the :ref:`examples `, ranging from very simple to more complex uses of confidence' capabilities. Contents -------- From b5e02d30ecd554bd8f8ded56c34354f68277a2fa Mon Sep 17 00:00:00 2001 From: Mattijs Ugen <144798+akaIDIOT@users.noreply.github.com> Date: Fri, 11 Mar 2022 16:22:05 +0100 Subject: [PATCH 04/12] Add an examples page and a glossary to refer to --- docs/examples.rst | 12 ++++++++++++ docs/glossary.rst | 23 +++++++++++++++++++++++ docs/index.rst | 8 ++------ 3 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 docs/examples.rst create mode 100644 docs/glossary.rst diff --git a/docs/examples.rst b/docs/examples.rst new file mode 100644 index 0000000..d71f3f6 --- /dev/null +++ b/docs/examples.rst @@ -0,0 +1,12 @@ +.. _examples: + +Examples +======== + +- Configuration from a runtime dict +- Configuration from a single file +- Configuration from multiple files +- Configuration from a name +- Configuration from multiple names +- Configuration from reordered loaders +- Configuration from mixed / custom loaders diff --git a/docs/glossary.rst b/docs/glossary.rst new file mode 100644 index 0000000..b6f8eac --- /dev/null +++ b/docs/glossary.rst @@ -0,0 +1,23 @@ +Glossary +======== + +.. glossary:: + :sorted: + + load order + … + + loader + … + + locality + … + + namespace + … + + precedence + … + + reference + … diff --git a/docs/index.rst b/docs/index.rst index ffaccef..d0fd526 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -13,12 +13,8 @@ Contents .. toctree:: :maxdepth: 2 + examples use recipes api - -Indices and tables ------------------- - -* :ref:`genindex` -* :ref:`search` + glossary From 8de8c4ecfdf7c446e3056b899bbc99ae9dfc4bc1 Mon Sep 17 00:00:00 2001 From: Mattijs Ugen <144798+akaIDIOT@users.noreply.github.com> Date: Mon, 14 Mar 2022 14:10:23 +0100 Subject: [PATCH 05/12] Improve first sentence, add todo to integrate the changelog --- docs/index.rst | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index d0fd526..9e1913f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,7 +1,7 @@ Configure with confidence ========================= -Confidence helps loading configuration options from file into a user-friendly object at runtime. +Confidence does two things: it helps loading configuration options from file(s) and presents those options as a user-friendly object at runtime. Inspired by the way Python's own ``pip`` reads its configuration (try ``pip config debug`` if you're not familiar with ``pip``'s configuration), confidence uses a similarly flexible, but deterministic approach to combining information from multiple configuration files. If that sounds awfully complicated, there's no requirement that you need to use anything that feels complicated. @@ -18,3 +18,10 @@ Contents recipes api glossary + +Changelog +--------- + +.. todo:: + + Integrate ``CHANGES.md`` here without having to duplicate it. From ec5d1e7b9b601f07f9974c8e7df024d11e1703a4 Mon Sep 17 00:00:00 2001 From: Mattijs Ugen <144798+akaIDIOT@users.noreply.github.com> Date: Mon, 14 Mar 2022 14:24:52 +0100 Subject: [PATCH 06/12] Formulate todos as todos, exclude from build result by default, override inclusion from nox --- docs/conf.py | 4 ++++ docs/examples.rst | 16 +++++++++------- docs/index.rst | 2 ++ docs/recipes.rst | 14 ++++++++------ docs/use.rst | 10 ++++++---- noxfile.py | 3 ++- 6 files changed, 31 insertions(+), 18 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index d93fa72..9786aea 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -35,6 +35,7 @@ # ones. extensions = [ 'sphinx.ext.autodoc', + 'sphinx.ext.todo', 'sphinx.ext.viewcode', ] @@ -57,6 +58,9 @@ autodoc_preserve_defaults = True +todo_include_todos = False + + default_role = 'py:obj' diff --git a/docs/examples.rst b/docs/examples.rst index d71f3f6..a5a92ef 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -3,10 +3,12 @@ Examples ======== -- Configuration from a runtime dict -- Configuration from a single file -- Configuration from multiple files -- Configuration from a name -- Configuration from multiple names -- Configuration from reordered loaders -- Configuration from mixed / custom loaders +.. todo:: + + - Configuration from a runtime dict + - Configuration from a single file + - Configuration from multiple files + - Configuration from a name + - Configuration from multiple names + - Configuration from reordered loaders + - Configuration from mixed / custom loaders diff --git a/docs/index.rst b/docs/index.rst index 9e1913f..72c38c2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -25,3 +25,5 @@ Changelog .. todo:: Integrate ``CHANGES.md`` here without having to duplicate it. + +.. todolist:: diff --git a/docs/recipes.rst b/docs/recipes.rst index 82d0ff2..1b7de72 100644 --- a/docs/recipes.rst +++ b/docs/recipes.rst @@ -1,9 +1,11 @@ Recipes ======= -- option subtrees - - default - - singular vs plural -- combining with command line arguments - - command line defaults from files - - command line is highest precedence +.. todo:: + + - option subtrees + - default + - singular vs plural + - combining with command line arguments + - command line defaults from files + - command line is highest precedence diff --git a/docs/use.rst b/docs/use.rst index 1a59ee2..fd6a97a 100644 --- a/docs/use.rst +++ b/docs/use.rst @@ -1,10 +1,12 @@ How to use confidence ===================== -- loading files -- loading by name -- creating `.Configuration` objects manually -- fail-fast: missing +.. todo:: + + - loading files + - loading by name + - creating `.Configuration` objects manually + - fail-fast: missing Logging ------- diff --git a/noxfile.py b/noxfile.py index 1de23f0..b2e4456 100644 --- a/noxfile.py +++ b/noxfile.py @@ -52,7 +52,8 @@ def docs(session): session.install('-r', 'requirements.txt') session.install('sphinx', 'sphinx-rtd-theme') - session.run('sphinx-build', '-b', 'html', 'docs/', 'dist/docs/') + # override setting to include todos here + session.run('sphinx-build', '-b', 'html', '-D', 'todo_include_todos=True', 'docs/', 'dist/docs/') @nox.session(python=oldest_python) From 8b3ab9ce3bc0743c0002488c9470cb5a5ec514bd Mon Sep 17 00:00:00 2001 From: Mattijs Ugen <144798+akaIDIOT@users.noreply.github.com> Date: Mon, 14 Mar 2022 14:48:55 +0100 Subject: [PATCH 07/12] Create simple example creating Configuration from a dict --- docs/examples.rst | 19 ++++++++++++++++++- docs/use.rst | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/examples.rst b/docs/examples.rst index a5a92ef..550bffa 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -3,9 +3,26 @@ Examples ======== +Although confidence is internally divided in a number of modules, all of the functions and types intended for use are available to import from the confidence module. + +.. code-block:: python + + # manually creating a Configuration object from a dict of values is about as + # simple as it sounds: + config = confidence.Configuration({ + 'service.host': 'example.com', + 'service.port': 443, + }) + + # suppose there's a function connect that takes two arguments + # we can connect to the configured host and port as such: + connection = connect(config.service.host, config.service.port) + # should the argument names align with the configuration (host and port), + # we could treat the configured namespace "service" as a dict and pass it as such: + connection = connect(**config.service) + .. todo:: - - Configuration from a runtime dict - Configuration from a single file - Configuration from multiple files - Configuration from a name diff --git a/docs/use.rst b/docs/use.rst index fd6a97a..495e92d 100644 --- a/docs/use.rst +++ b/docs/use.rst @@ -6,6 +6,7 @@ How to use confidence - loading files - loading by name - creating `.Configuration` objects manually + - pass values as ``**kwargs`` - fail-fast: missing Logging From 9a1084e9b8b381c313505e5b7e3c643114e12d82 Mon Sep 17 00:00:00 2001 From: Mattijs Ugen <144798+akaIDIOT@users.noreply.github.com> Date: Mon, 14 Mar 2022 16:29:17 +0100 Subject: [PATCH 08/12] Add example reading configuration from file --- docs/examples.rst | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/examples.rst b/docs/examples.rst index 550bffa..0d92f95 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -21,9 +21,29 @@ Although confidence is internally divided in a number of modules, all of the fun # we could treat the configured namespace "service" as a dict and pass it as such: connection = connect(**config.service) +Wrapping a `dict` with a `Configuration` is nice, but configuration is more often found in files. +Confidence loads configuration from file in the YAML format: + +.. code-block:: yaml + + # suppose we'd save this as path/to/file.yaml + service: + host: example.com + port: 443 + # note that we could also have expressed the two properties as + # service.host: ... + # service.port: ... + # dotted names are equivalent to nested ones + +.. code-block:: python + + # loadf simply takes a path or path-like to load configuration from + config = confidence.loadf('path/to/file.yaml') + # the result is the same as the example above, we can use config.service like we would a dict + connection = connect(**config.service) + .. todo:: - - Configuration from a single file - Configuration from multiple files - Configuration from a name - Configuration from multiple names From e0eb19bf0b500e0e27914eeb2acafbc171a1dbcc Mon Sep 17 00:00:00 2001 From: Mattijs Ugen <144798+akaIDIOT@users.noreply.github.com> Date: Mon, 14 Mar 2022 16:35:31 +0100 Subject: [PATCH 09/12] Add example reading configuration from multiple files --- docs/examples.rst | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/docs/examples.rst b/docs/examples.rst index 0d92f95..b1d13f6 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -42,9 +42,34 @@ Confidence loads configuration from file in the YAML format: # the result is the same as the example above, we can use config.service like we would a dict connection = connect(**config.service) +If you split your configuration over multiple files as they contain configuration for different things, like a service to connect to and some local paths to store data, confidence can load them both as if they were one: + +.. code-block:: yaml + + # some system-wide configuration in /etc/paths.yaml + paths: + data: /storage/data + backup: /mnt/backup/data + +.. code-block:: yaml + + # service configuration as before, stored in path/to/service.yaml + service.host: example.com + service.port: 443 + +.. code-block:: python + + # loadf can take multiple files, the contents of which are combined into a + # single Configuration object + config = confidence.loadf('/etc/paths.yaml', 'path/to/service.yaml') + + # there's still something to connect to the service + connection = connect(**config.service) + # and some extra things that configure the place to backup to + connection.backup_to(config.paths.backup) + .. todo:: - - Configuration from multiple files - Configuration from a name - Configuration from multiple names - Configuration from reordered loaders From b38ee435ede962fc07600bdaea05f90c854413ad Mon Sep 17 00:00:00 2001 From: Mattijs Ugen <144798+akaIDIOT@users.noreply.github.com> Date: Tue, 6 Sep 2022 15:07:16 +0200 Subject: [PATCH 10/12] Add example overriding a configuration value from another file --- docs/examples.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/examples.rst b/docs/examples.rst index b1d13f6..d8b5e77 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -68,6 +68,26 @@ If you split your configuration over multiple files as they contain configuratio # and some extra things that configure the place to backup to connection.backup_to(config.paths.backup) +If values from multiple files overlap (like if ``/etc/paths.yaml`` would contain ``service.port: 80``), things become slightly more complicated. +Confidence uses a predictable :term:`precedence` of content here: the value that gets loaded last has the highest precedence (or 'wins'). +`loadf` will load content in the order of the arguments that get passed, so ``service.port`` would be 443, as defined in ``path/to/service.yaml``. +You can use this behaviour to define defaults somewhere, that get overridden later: + +.. code-block:: yaml + + # some system-wide configuration in /etc/paths.yaml + service.port: 80 + + paths: + data: /storage/data + backup: /mnt/backup/data + +.. code-block:: yaml + + service: + host: example.com + port: 443 + .. todo:: - Configuration from a name From 39a4203097f1f25e9e5fc2aa5c3cf30686affec0 Mon Sep 17 00:00:00 2001 From: Mattijs Ugen <144798+akaIDIOT@users.noreply.github.com> Date: Tue, 6 Sep 2022 15:10:05 +0200 Subject: [PATCH 11/12] Add headers to examples --- docs/examples.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/examples.rst b/docs/examples.rst index d8b5e77..b8d9d8b 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -21,6 +21,9 @@ Although confidence is internally divided in a number of modules, all of the fun # we could treat the configured namespace "service" as a dict and pass it as such: connection = connect(**config.service) +Reading configuration from a file +--------------------------------- + Wrapping a `dict` with a `Configuration` is nice, but configuration is more often found in files. Confidence loads configuration from file in the YAML format: @@ -42,6 +45,9 @@ Confidence loads configuration from file in the YAML format: # the result is the same as the example above, we can use config.service like we would a dict connection = connect(**config.service) +Reading from multiple files +--------------------------- + If you split your configuration over multiple files as they contain configuration for different things, like a service to connect to and some local paths to store data, confidence can load them both as if they were one: .. code-block:: yaml @@ -68,6 +74,9 @@ If you split your configuration over multiple files as they contain configuratio # and some extra things that configure the place to backup to connection.backup_to(config.paths.backup) +Overriding defaults from one file to the next +--------------------------------------------- + If values from multiple files overlap (like if ``/etc/paths.yaml`` would contain ``service.port: 80``), things become slightly more complicated. Confidence uses a predictable :term:`precedence` of content here: the value that gets loaded last has the highest precedence (or 'wins'). `loadf` will load content in the order of the arguments that get passed, so ``service.port`` would be 443, as defined in ``path/to/service.yaml``. From 502ab1b583144b71931f258887d178a2fbc14636 Mon Sep 17 00:00:00 2001 From: Mattijs Ugen <144798+akaIDIOT@users.noreply.github.com> Date: Tue, 6 Sep 2022 15:13:55 +0200 Subject: [PATCH 12/12] Add a quick overview to docs index --- docs/index.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 72c38c2..3990726 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,6 +7,12 @@ confidence uses a similarly flexible, but deterministic approach to combining in If that sounds awfully complicated, there's no requirement that you need to use anything that feels complicated. See the :ref:`examples `, ranging from very simple to more complex uses of confidence' capabilities. +As a quick overview, confidence contains the following features: + +- dict-like `Configuration` object supporting attribute access to configured values; +- customizable loading of multiple sources (files, environment variables, …) into a single object with deterministic precedence of those sources; +- the ability to make and resolve references to values or entire namespaces. + Contents -------- @@ -19,9 +25,6 @@ Contents api glossary -Changelog ---------- - .. todo:: Integrate ``CHANGES.md`` here without having to duplicate it.