diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000..a6c1f7a
--- /dev/null
+++ b/.envrc
@@ -0,0 +1 @@
+layout git
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..05b585e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+**/__pycache__
+**/.ipynb_checkpoints*
diff --git a/BRANDING b/BRANDING
new file mode 100644
index 0000000..6205435
--- /dev/null
+++ b/BRANDING
@@ -0,0 +1,14 @@
+
+
+https://nicetranslator.com/
+
+
+* Arbre/Tree*
+Kheops => Arbre en Italien TOP 1
+Copac => Romanian TOP 2
+strom => Slovak
+
+* hierarchy
+jerarquia .... deja pris lol
+hiera ... deja pris lol
+
diff --git a/OLD_docs/app_schema.json b/OLD_docs/app_schema.json
new file mode 100644
index 0000000..f927d5c
--- /dev/null
+++ b/OLD_docs/app_schema.json
@@ -0,0 +1,179 @@
+{
+ "config_schema": {},
+ "items": {
+ "core_schema": {
+ "engine": {
+ "type": "string",
+ "default": "jerakia",
+ "optional": false
+ },
+ "value": {
+ "default": "UNSET",
+ "optional": false
+ }
+ },
+ "plugin": {
+ "engine": {
+ "jerakia_schema": {
+ "path": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "glob": {
+ "default": "ansible.yml",
+ "anyOf": [
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ },
+ "backend": {
+ "hier_schema": {
+ "hier": {
+ "default": null,
+ "optional": true,
+ "oneOf": [
+ {
+ "type": "null"
+ },
+ {
+ "type": "string"
+ },
+ {
+ "additionalProperties": true,
+ "properties": {
+ "data": {
+ "default": null,
+ "anyOf": [
+ {
+ "type": "null"
+ },
+ {
+ "type": "string"
+ },
+ {
+ "type": "array"
+ }
+ ]
+ },
+ "var": {
+ "type": "string",
+ "default": "hier_item",
+ "optional": true
+ },
+ "separator": {
+ "type": "string",
+ "default": "/",
+ "optional": true
+ },
+ "reversed": {
+ "type": "boolean",
+ "default": false,
+ "optional": true
+ }
+ }
+ }
+ ]
+ }
+ },
+ "loop_schema": {
+ "loop": {
+ "description": [
+ "\n This module helps to loop over a backend\n "
+ ],
+ "default": null,
+ "optional": true,
+ "examples": [
+ {
+ "value": "site/{{ loop_env }}/config/{{ os }}",
+ "loop": {
+ "var": "loop_env",
+ "data": [
+ "dev",
+ "preprod",
+ "prod"
+ ]
+ },
+ "comment": "The module will loop three time over the value, and the variable `loop_env` will consecutely have `dev`, `preprod` and `prod` as value"
+ },
+ {
+ "value": "site/{{ loop_env2 }}/config/{{ os }}",
+ "loop": {
+ "var": "loop_env2",
+ "data": "my_scope_var"
+ },
+ "comment": "Like the previous example, but it will fetch the list from any scope variables"
+ },
+ {
+ "loop": null,
+ "comment": "Disable this module, no loop will operate"
+ }
+ ],
+ "oneOf": [
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "default": {},
+ "title": "Complete config",
+ "description": "",
+ "properties": {
+ "data": {
+ "default": null,
+ "optional": false,
+ "title": "Module configuration",
+ "description": "Data list used for iterations. It only accept lists as type. It disable the module if set to `null`.",
+ "anyOf": [
+ {
+ "type": "null",
+ "title": "Disable Module",
+ "description": "Disable the module"
+ },
+ {
+ "type": "string",
+ "title": "Scope variable",
+ "description": "Will look the value of the loop list from the scope. TOFIX: What if variablle does not exists?"
+ },
+ {
+ "type": "array",
+ "title": "Hardcoded list",
+ "description": "Simply enter the list of value to be iterated to."
+ }
+ ]
+ },
+ "var": {
+ "type": "string",
+ "default": "loop_item",
+ "optional": true,
+ "title": "Module configuration",
+ "description": "Name of the variable to be used in templating language"
+ }
+ }
+ },
+ {
+ "type": "string",
+ "title": "Short config",
+ "description": "If set to string, it will define the name of the variable to lookup into the scope."
+ },
+ {
+ "type": "null",
+ "title": "Disable",
+ "description": "If set to null, it disable the module"
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/OLD_docs/build_doc.sh b/OLD_docs/build_doc.sh
new file mode 100755
index 0000000..c726b46
--- /dev/null
+++ b/OLD_docs/build_doc.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+set -eux
+
+APP_SCHEMA=app_schema.json
+
+gen_doc ()
+{
+ local kind=$1
+ local dir=$2
+ local config=$3
+
+ [[ ! -z "$dir" ]] || exit 2
+ rm -rf "$dir" && mkdir -p "$dir"
+
+ generate-schema-doc \
+ --config-file "$config" \
+ "$APP_SCHEMA" \
+ "$dir"/"main.$kind"
+}
+
+
+main ()
+{
+ kheops schema > "$APP_SCHEMA"
+ for i in html md; do
+ gen_doc "$i" "docs_$i" "doc_config_${i}.yaml"
+ done
+}
+
+main
+
+
diff --git a/OLD_docs/doc_config_html.yaml b/OLD_docs/doc_config_html.yaml
new file mode 100644
index 0000000..944869b
--- /dev/null
+++ b/OLD_docs/doc_config_html.yaml
@@ -0,0 +1,5 @@
+---
+template_name: js
+description_is_markdown: true
+expand_buttons: true
+copy_js: false
diff --git a/OLD_docs/doc_config_md.yaml b/OLD_docs/doc_config_md.yaml
new file mode 100644
index 0000000..c5b5b7b
--- /dev/null
+++ b/OLD_docs/doc_config_md.yaml
@@ -0,0 +1,5 @@
+---
+template_name: md
+description_is_markdown: true
+expand_buttons: true
+copy_js: false
diff --git a/OLD_docs/docs_html/main.html b/OLD_docs/docs_html/main.html
new file mode 100644
index 0000000..753b703
--- /dev/null
+++ b/OLD_docs/docs_html/main.html
@@ -0,0 +1 @@
+
Schema Docs
Type: object
\ No newline at end of file
diff --git a/OLD_docs/docs_html/schema_doc.css b/OLD_docs/docs_html/schema_doc.css
new file mode 100644
index 0000000..83897d8
--- /dev/null
+++ b/OLD_docs/docs_html/schema_doc.css
@@ -0,0 +1,180 @@
+body {
+ font: 16px/1.5em "Overpass", "Open Sans", Helvetica, sans-serif;
+ color: #333;
+ font-weight: 300;
+ padding: 40px;
+}
+
+.btn.btn-link {
+ font-size: 18px;
+}
+
+.jsfh-animated-property {
+ animation: eclair;
+ animation-iteration-count: 1;
+ animation-fill-mode: forwards;
+ animation-duration: .75s;
+
+}
+
+@keyframes eclair {
+ 0%,100% {
+ transform: scale(1);
+ }
+ 50% {
+ transform: scale(1.03);
+ }
+}
+
+.btn.btn-primary {
+ margin: 10px;
+}
+
+.btn.example-show.collapsed:before {
+ content: "show"
+}
+
+.btn.example-show:before {
+ content: "hide"
+}
+
+.description.collapse:not(.show) {
+ max-height: 100px !important;
+ overflow: hidden;
+
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+}
+
+.description.collapsing {
+ min-height: 100px !important;
+}
+
+.collapse-description-link.collapsed:after {
+ content: '+ Read More';
+}
+
+.collapse-description-link:not(.collapsed):after {
+ content: '- Read Less';
+}
+
+.badge {
+ font-size: 100%;
+ margin-bottom: 0.5rem;
+ margin-top: 0.5rem;
+}
+
+.badge.value-type {
+ font-size: 120%;
+ margin-right: 5px;
+ margin-bottom: 10px;
+}
+
+
+.badge.default-value {
+ font-size: 120%;
+ margin-left: 5px;
+ margin-bottom: 10px;
+}
+
+.badge.restriction {
+ display: inline-block;
+}
+
+.badge.required-property,.badge.deprecated-property,.badge.pattern-property,.badge.no-additional {
+ font-size: 100%;
+ margin-left: 10px;
+}
+
+.accordion div.card:only-child {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.examples {
+ padding: 1rem !important;
+}
+
+.examples pre {
+ margin-bottom: 0;
+}
+
+.highlight.jumbotron {
+ padding: 1rem !important;
+}
+
+.generated-by-footer {
+ margin-top: 1em;
+ text-align: right;
+}
+
+/* From https://github.com/richleland/pygments-css/blob/master/friendly.css, see https://github.com/trentm/python-markdown2/wiki/fenced-code-blocks */
+.highlight { background: #e9ecef; } /* Changed from #f0f0f0 in the original style to be the same as bootstrap's jumbotron */
+.highlight .hll { background-color: #ffffcc }
+.highlight .c { color: #60a0b0; font-style: italic } /* Comment */
+.highlight .err { border: 1px solid #FF0000 } /* Error */
+.highlight .k { color: #007020; font-weight: bold } /* Keyword */
+.highlight .o { color: #666666 } /* Operator */
+.highlight .ch { color: #60a0b0; font-style: italic } /* Comment.Hashbang */
+.highlight .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */
+.highlight .cp { color: #007020 } /* Comment.Preproc */
+.highlight .cpf { color: #60a0b0; font-style: italic } /* Comment.PreprocFile */
+.highlight .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */
+.highlight .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */
+.highlight .gd { color: #A00000 } /* Generic.Deleted */
+.highlight .ge { font-style: italic } /* Generic.Emph */
+.highlight .gr { color: #FF0000 } /* Generic.Error */
+.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.highlight .gi { color: #00A000 } /* Generic.Inserted */
+.highlight .go { color: #888888 } /* Generic.Output */
+.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
+.highlight .gs { font-weight: bold } /* Generic.Strong */
+.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.highlight .gt { color: #0044DD } /* Generic.Traceback */
+.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
+.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
+.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
+.highlight .kp { color: #007020 } /* Keyword.Pseudo */
+.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
+.highlight .kt { color: #902000 } /* Keyword.Type */
+.highlight .m { color: #40a070 } /* Literal.Number */
+.highlight .s { color: #4070a0 } /* Literal.String */
+.highlight .na { color: #4070a0 } /* Name.Attribute */
+.highlight .nb { color: #007020 } /* Name.Builtin */
+.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
+.highlight .no { color: #60add5 } /* Name.Constant */
+.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
+.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
+.highlight .ne { color: #007020 } /* Name.Exception */
+.highlight .nf { color: #06287e } /* Name.Function */
+.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
+.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
+.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
+.highlight .nv { color: #bb60d5 } /* Name.Variable */
+.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
+.highlight .w { color: #bbbbbb } /* Text.Whitespace */
+.highlight .mb { color: #40a070 } /* Literal.Number.Bin */
+.highlight .mf { color: #40a070 } /* Literal.Number.Float */
+.highlight .mh { color: #40a070 } /* Literal.Number.Hex */
+.highlight .mi { color: #40a070 } /* Literal.Number.Integer */
+.highlight .mo { color: #40a070 } /* Literal.Number.Oct */
+.highlight .sa { color: #4070a0 } /* Literal.String.Affix */
+.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
+.highlight .sc { color: #4070a0 } /* Literal.String.Char */
+.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
+.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
+.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
+.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
+.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
+.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
+.highlight .sx { color: #c65d09 } /* Literal.String.Other */
+.highlight .sr { color: #235388 } /* Literal.String.Regex */
+.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
+.highlight .ss { color: #517918 } /* Literal.String.Symbol */
+.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
+.highlight .fm { color: #06287e } /* Name.Function.Magic */
+.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
+.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
+.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
+.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
+.highlight .il { color: #40a070 } /* Literal.Number.Integer.Long */
\ No newline at end of file
diff --git a/OLD_docs/docs_md/main.md b/OLD_docs/docs_md/main.md
new file mode 100644
index 0000000..2fc530a
--- /dev/null
+++ b/OLD_docs/docs_md/main.md
@@ -0,0 +1,9 @@
+# Schema Docs
+
+| Type | `object` |
+| ------------------------- | ------------------------------------------------------------------------- |
+| **Additional properties** | [[Any type: allowed]](# "Additional Properties of any type are allowed.") |
+| | |
+
+----------------------------------------------------------------------------------------------------------------------------
+Generated using [json-schema-for-humans](https://github.com/coveooss/json-schema-for-humans) on 2022-01-26 at 18:04:57 -0500
\ No newline at end of file
diff --git a/README.md.backup b/README.md.backup
new file mode 100644
index 0000000..2c3a0dc
--- /dev/null
+++ b/README.md.backup
@@ -0,0 +1,131 @@
+# Kheops
+
+
+Introduction:
+
+> [~~Jerakia~~](https://web.archive.org/web/20180829194211/http://jerakia.io/documentation/
+)Kheops is a tool that performs key value lookups against a variety of pluggable data stores. It does this using a top-down hierarchical set of queries that allow you to define global values and override them at different levels of a configurable hierarchy.
+
+> This has many use cases, including infrastructure management where you often have configuration values defined at a global level but wish to override these values based on certain factors such as the environment or location of the request.
+
+Kheops is a fresh python rewrite of this project. It does not attempt to have the same features, and it's work in progress project.
+
+
+## Getting Started
+
+These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.
+
+### Prerequisites
+
+What things you need to install the software and how to install them
+
+```
+virtualenv -p python3 venv
+. venv/bin/activate
+pip install --upgrade pip -y
+```
+
+### Installing
+
+Install Kheops
+
+```
+pip install kheops
+```
+
+And check it works:
+
+```
+kheops --help
+```
+
+Now you can test the examples, and learn how to use it [here](/lost).
+
+```
+kheops --config examples/01_simple/ hello
+kheops --config examples/01_simple/ hello -e site=
+kheops --config examples/01_simple/ hello -e site=
+```
+
+## Learning Kheops
+
+
+
+
+
+
+
+
+## Running the tests
+
+Explain how to run the automated tests for this system
+
+### Break down into end to end tests
+
+Explain what these tests test and why
+
+```
+Give an example
+```
+
+### And coding style tests
+
+Explain what these tests test and why
+
+```
+Give an example
+```
+
+## Deployment
+
+Add additional notes about how to deploy this on a live system
+
+## Built With
+
+* [Dropwizard](http://www.dropwizard.io/1.0.2/docs/) - The web framework used
+* [Maven](https://maven.apache.org/) - Dependency Management
+* [ROME](https://rometools.github.io/rome/) - Used to generate RSS Feeds
+
+## Contributing
+
+Please read [CONTRIBUTING.md](https://gist.github.com/PurpleBooth/b24679402957c63ec426) for details on our code of conduct, and the process for submitting pull requests to us.
+
+## Versioning
+
+We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/your/project/tags).
+
+## Authors
+
+* **Billie Thompson** - *Initial work* - [PurpleBooth](https://github.com/PurpleBooth)
+
+See also the list of [contributors](https://github.com/your/project/contributors) who participated in this project.
+
+## License
+
+This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
+
+## Acknowledgments
+
+* Hat tip to anyone whose code was used
+* Inspiration
+* etc
+
+
+
+A jerakia old website:
+https://web.archive.org/web/20190209052035/http://jerakia.io/
+
+https://web.archive.org/web/20180829194211/http://jerakia.io/documentation/
+
+
+
+key-value configuration data lookup system
+
+
+A VERSATILE DATA LOOKUP SYSTEM
+
+Jerakia is a tool that performs key value lookups against a variety of pluggable data stores. It does this using a top-down hierarchical set of queries that allow you to define global values and override them at different levels of a configurable hierarchy.
+
+This has many use cases, including infrastructure management where you often have configuration values defined at a global level but wish to override these values based on certain factors such as the environment or location of the request.
+
+Kheops is a key-value configuration data lookup system. It can performs a key value lookup against a variety of data stores.
\ No newline at end of file
diff --git a/dist/kheops-0.1.0-py3-none-any.whl b/dist/kheops-0.1.0-py3-none-any.whl
new file mode 100644
index 0000000..3ead73b
Binary files /dev/null and b/dist/kheops-0.1.0-py3-none-any.whl differ
diff --git a/dist/kheops-0.1.0.tar.gz b/dist/kheops-0.1.0.tar.gz
new file mode 100644
index 0000000..7da2a95
Binary files /dev/null and b/dist/kheops-0.1.0.tar.gz differ
diff --git a/docs/_build/doctrees/api/kheops.doctree b/docs/_build/doctrees/api/kheops.doctree
new file mode 100644
index 0000000..ff2ba63
Binary files /dev/null and b/docs/_build/doctrees/api/kheops.doctree differ
diff --git a/docs/_build/doctrees/api/kheops.plugin.backend.doctree b/docs/_build/doctrees/api/kheops.plugin.backend.doctree
new file mode 100644
index 0000000..8183094
Binary files /dev/null and b/docs/_build/doctrees/api/kheops.plugin.backend.doctree differ
diff --git a/docs/_build/doctrees/api/kheops.plugin.doctree b/docs/_build/doctrees/api/kheops.plugin.doctree
new file mode 100644
index 0000000..f4f4e92
Binary files /dev/null and b/docs/_build/doctrees/api/kheops.plugin.doctree differ
diff --git a/docs/_build/doctrees/api/kheops.plugin.scope.doctree b/docs/_build/doctrees/api/kheops.plugin.scope.doctree
new file mode 100644
index 0000000..00af2d4
Binary files /dev/null and b/docs/_build/doctrees/api/kheops.plugin.scope.doctree differ
diff --git a/docs/_build/doctrees/api/kheops.plugin.strategy.doctree b/docs/_build/doctrees/api/kheops.plugin.strategy.doctree
new file mode 100644
index 0000000..11521a5
Binary files /dev/null and b/docs/_build/doctrees/api/kheops.plugin.strategy.doctree differ
diff --git a/docs/_build/doctrees/api/modules.doctree b/docs/_build/doctrees/api/modules.doctree
new file mode 100644
index 0000000..5fe2041
Binary files /dev/null and b/docs/_build/doctrees/api/modules.doctree differ
diff --git a/docs/_build/doctrees/docs/app/cli.doctree b/docs/_build/doctrees/docs/app/cli.doctree
new file mode 100644
index 0000000..5591b4b
Binary files /dev/null and b/docs/_build/doctrees/docs/app/cli.doctree differ
diff --git a/docs/_build/doctrees/docs/app/config.doctree b/docs/_build/doctrees/docs/app/config.doctree
new file mode 100644
index 0000000..47438d2
Binary files /dev/null and b/docs/_build/doctrees/docs/app/config.doctree differ
diff --git a/docs/_build/doctrees/docs/app/examples.doctree b/docs/_build/doctrees/docs/app/examples.doctree
new file mode 100644
index 0000000..8e9cb65
Binary files /dev/null and b/docs/_build/doctrees/docs/app/examples.doctree differ
diff --git a/docs/_build/doctrees/docs/app/index.doctree b/docs/_build/doctrees/docs/app/index.doctree
new file mode 100644
index 0000000..089e112
Binary files /dev/null and b/docs/_build/doctrees/docs/app/index.doctree differ
diff --git a/docs/_build/doctrees/docs/app/installation.doctree b/docs/_build/doctrees/docs/app/installation.doctree
new file mode 100644
index 0000000..1641936
Binary files /dev/null and b/docs/_build/doctrees/docs/app/installation.doctree differ
diff --git a/docs/_build/doctrees/docs/app/internal.doctree b/docs/_build/doctrees/docs/app/internal.doctree
new file mode 100644
index 0000000..1cdeeb8
Binary files /dev/null and b/docs/_build/doctrees/docs/app/internal.doctree differ
diff --git a/docs/_build/doctrees/docs/app/usage.doctree b/docs/_build/doctrees/docs/app/usage.doctree
new file mode 100644
index 0000000..e553281
Binary files /dev/null and b/docs/_build/doctrees/docs/app/usage.doctree differ
diff --git a/docs/_build/doctrees/docs/guide/ansible/index.doctree b/docs/_build/doctrees/docs/guide/ansible/index.doctree
new file mode 100644
index 0000000..4fdeb72
Binary files /dev/null and b/docs/_build/doctrees/docs/guide/ansible/index.doctree differ
diff --git a/docs/_build/doctrees/docs/guide/best_practices.doctree b/docs/_build/doctrees/docs/guide/best_practices.doctree
new file mode 100644
index 0000000..27bc0b7
Binary files /dev/null and b/docs/_build/doctrees/docs/guide/best_practices.doctree differ
diff --git a/docs/_build/doctrees/docs/guide/index.doctree b/docs/_build/doctrees/docs/guide/index.doctree
new file mode 100644
index 0000000..943fa90
Binary files /dev/null and b/docs/_build/doctrees/docs/guide/index.doctree differ
diff --git a/docs/_build/doctrees/docs/learn/100.doctree b/docs/_build/doctrees/docs/learn/100.doctree
new file mode 100644
index 0000000..3bed277
Binary files /dev/null and b/docs/_build/doctrees/docs/learn/100.doctree differ
diff --git a/docs/_build/doctrees/docs/learn/101.doctree b/docs/_build/doctrees/docs/learn/101.doctree
new file mode 100644
index 0000000..73bef1a
Binary files /dev/null and b/docs/_build/doctrees/docs/learn/101.doctree differ
diff --git a/docs/_build/doctrees/docs/learn/102.doctree b/docs/_build/doctrees/docs/learn/102.doctree
new file mode 100644
index 0000000..c8785ca
Binary files /dev/null and b/docs/_build/doctrees/docs/learn/102.doctree differ
diff --git a/docs/_build/doctrees/docs/learn/105.doctree b/docs/_build/doctrees/docs/learn/105.doctree
new file mode 100644
index 0000000..8cebc05
Binary files /dev/null and b/docs/_build/doctrees/docs/learn/105.doctree differ
diff --git a/docs/_build/doctrees/docs/learn/index.doctree b/docs/_build/doctrees/docs/learn/index.doctree
new file mode 100644
index 0000000..95d662d
Binary files /dev/null and b/docs/_build/doctrees/docs/learn/index.doctree differ
diff --git a/docs/_build/doctrees/environment.pickle b/docs/_build/doctrees/environment.pickle
new file mode 100644
index 0000000..837278a
Binary files /dev/null and b/docs/_build/doctrees/environment.pickle differ
diff --git a/docs/_build/doctrees/index.doctree b/docs/_build/doctrees/index.doctree
new file mode 100644
index 0000000..e632d0a
Binary files /dev/null and b/docs/_build/doctrees/index.doctree differ
diff --git a/docs/_build/doctrees/learn/learn101.doctree b/docs/_build/doctrees/learn/learn101.doctree
new file mode 100644
index 0000000..21f3bbe
Binary files /dev/null and b/docs/_build/doctrees/learn/learn101.doctree differ
diff --git a/docs/_build/html/.buildinfo b/docs/_build/html/.buildinfo
new file mode 100644
index 0000000..9220a35
--- /dev/null
+++ b/docs/_build/html/.buildinfo
@@ -0,0 +1,4 @@
+# Sphinx build info version 1
+# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
+config: 1a2b02b2d095b63c541d520c0d4bbc59
+tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/docs/_build/html/_images/kheops_brand.png b/docs/_build/html/_images/kheops_brand.png
new file mode 100644
index 0000000..22ca848
Binary files /dev/null and b/docs/_build/html/_images/kheops_brand.png differ
diff --git a/docs/_build/html/_sources/api/kheops.plugin.backend.rst.txt b/docs/_build/html/_sources/api/kheops.plugin.backend.rst.txt
new file mode 100644
index 0000000..77d53bb
--- /dev/null
+++ b/docs/_build/html/_sources/api/kheops.plugin.backend.rst.txt
@@ -0,0 +1,18 @@
+kheops.plugin.backend package
+=============================
+
+.. automodule:: kheops.plugin.backend
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+Submodules
+----------
+
+kheops.plugin.backend.file module
+---------------------------------
+
+.. automodule:: kheops.plugin.backend.file
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/api/kheops.plugin.rst.txt b/docs/_build/html/_sources/api/kheops.plugin.rst.txt
new file mode 100644
index 0000000..444a3bc
--- /dev/null
+++ b/docs/_build/html/_sources/api/kheops.plugin.rst.txt
@@ -0,0 +1,28 @@
+kheops.plugin package
+=====================
+
+.. automodule:: kheops.plugin
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+Subpackages
+-----------
+
+.. toctree::
+ :maxdepth: 4
+
+ kheops.plugin.backend
+ kheops.plugin.scope
+ kheops.plugin.strategy
+
+Submodules
+----------
+
+kheops.plugin.common module
+---------------------------
+
+.. automodule:: kheops.plugin.common
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/api/kheops.plugin.scope.rst.txt b/docs/_build/html/_sources/api/kheops.plugin.scope.rst.txt
new file mode 100644
index 0000000..5d2c06d
--- /dev/null
+++ b/docs/_build/html/_sources/api/kheops.plugin.scope.rst.txt
@@ -0,0 +1,26 @@
+kheops.plugin.scope package
+===========================
+
+.. automodule:: kheops.plugin.scope
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+Submodules
+----------
+
+kheops.plugin.scope.hier module
+-------------------------------
+
+.. automodule:: kheops.plugin.scope.hier
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+kheops.plugin.scope.loop module
+-------------------------------
+
+.. automodule:: kheops.plugin.scope.loop
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/api/kheops.plugin.strategy.rst.txt b/docs/_build/html/_sources/api/kheops.plugin.strategy.rst.txt
new file mode 100644
index 0000000..5497258
--- /dev/null
+++ b/docs/_build/html/_sources/api/kheops.plugin.strategy.rst.txt
@@ -0,0 +1,26 @@
+kheops.plugin.strategy package
+==============================
+
+.. automodule:: kheops.plugin.strategy
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+Submodules
+----------
+
+kheops.plugin.strategy.last module
+----------------------------------
+
+.. automodule:: kheops.plugin.strategy.last
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+kheops.plugin.strategy.merge\_deep module
+-----------------------------------------
+
+.. automodule:: kheops.plugin.strategy.merge_deep
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/api/kheops.rst.txt b/docs/_build/html/_sources/api/kheops.rst.txt
new file mode 100644
index 0000000..4af2e99
--- /dev/null
+++ b/docs/_build/html/_sources/api/kheops.rst.txt
@@ -0,0 +1,50 @@
+kheops package
+==============
+
+.. automodule:: kheops
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+Subpackages
+-----------
+
+.. toctree::
+ :maxdepth: 4
+
+ kheops.plugin
+
+Submodules
+----------
+
+kheops.app module
+-----------------
+
+.. automodule:: kheops.app
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+kheops.cli module
+-----------------
+
+.. automodule:: kheops.cli
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+kheops.controllers module
+-------------------------
+
+.. automodule:: kheops.controllers
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+kheops.utils module
+-------------------
+
+.. automodule:: kheops.utils
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/api/modules.rst.txt b/docs/_build/html/_sources/api/modules.rst.txt
new file mode 100644
index 0000000..3a299b5
--- /dev/null
+++ b/docs/_build/html/_sources/api/modules.rst.txt
@@ -0,0 +1,7 @@
+kheops
+======
+
+.. toctree::
+ :maxdepth: 4
+
+ kheops
diff --git a/docs/_build/html/_sources/docs/app/cli.md.txt b/docs/_build/html/_sources/docs/app/cli.md.txt
new file mode 100644
index 0000000..432929e
--- /dev/null
+++ b/docs/_build/html/_sources/docs/app/cli.md.txt
@@ -0,0 +1,2 @@
+# CLI
+
diff --git a/docs/_build/html/_sources/docs/app/config.md.txt b/docs/_build/html/_sources/docs/app/config.md.txt
new file mode 100644
index 0000000..46ac1e6
--- /dev/null
+++ b/docs/_build/html/_sources/docs/app/config.md.txt
@@ -0,0 +1 @@
+# Config
diff --git a/docs/_build/html/_sources/docs/app/examples.rst.txt b/docs/_build/html/_sources/docs/app/examples.rst.txt
new file mode 100644
index 0000000..61a23fa
--- /dev/null
+++ b/docs/_build/html/_sources/docs/app/examples.rst.txt
@@ -0,0 +1,8 @@
+
+Examples ...
+======================
+
+examples
+
+.. contents:: Table of Contents
+
diff --git a/docs/_build/html/_sources/docs/app/index.rst.txt b/docs/_build/html/_sources/docs/app/index.rst.txt
new file mode 100644
index 0000000..6366fde
--- /dev/null
+++ b/docs/_build/html/_sources/docs/app/index.rst.txt
@@ -0,0 +1,18 @@
+
+
+Application
+===========
+
+.. toctree::
+ :maxdepth: 4
+ :caption: Contents:
+
+ installation.rst
+ usage.rst
+ cli.md
+ config.md
+ examples.rst
+ internal.md
+
+
+Application documentation
diff --git a/docs/_build/html/_sources/docs/app/installation.rst.txt b/docs/_build/html/_sources/docs/app/installation.rst.txt
new file mode 100644
index 0000000..99ecdc7
--- /dev/null
+++ b/docs/_build/html/_sources/docs/app/installation.rst.txt
@@ -0,0 +1,5 @@
+
+Instalation procedure
+======================
+
+
diff --git a/docs/_build/html/_sources/docs/app/internal.md.txt b/docs/_build/html/_sources/docs/app/internal.md.txt
new file mode 100644
index 0000000..5bf9020
--- /dev/null
+++ b/docs/_build/html/_sources/docs/app/internal.md.txt
@@ -0,0 +1,34 @@
+
+# Internals
+
+
+* 101: TECHINICAL How works a hierarchical data lookup?
+ - Query a key
+ + Can be a simple string or complex data
+ + Can be anything in json compatible
+ - Kheops will resolve query in 2 parts:
+ + It will first look in different locations the key. It is usually files, but it can also be an url or anything. The queried data must be a valid json data type (TOFIX: So it works also for yaml, toml .... it supports [anyconfig](https://github.com/ssato/python-anyconfig) )
+ * Example: The `path` strategy will allow you to target
+ + Then it will process all results and load a strategy to resolve which results to keep.
+ Example: The `last` strategy consists in keeping always the last result while the `merge` strategy consists in merging inteligentelly data. This is quite useful for dict or lists.
+ +
+ - Lookup data in a tree of files
+ + Goes sequentially according the backends list
+ * Backend/Engine list is modular
+ * Engine Plugin: Jerakia/HIera/Ansible/Curl
+ * Backend Plugin: loop/hier
+ + All result are returned, and then the rules are applied
+ + Rules match to a key and apply a strategy (essentially determine if and how the different value are merged or replaced). It can also apply filter to the result and modify its content (future).
+ * This is modular
+ * Strategy: last/schema
+ - Last will always take the last found value, whatever what it previously found.
+ - schema: It will take into account the strucutre of the data and try to merge them intelligentelly. See more on
+ + Then it returns the result
+ - Use cases
+ + Ansible integration
+ + Generic SOT
+ + Rest API (Future)
+ + More !!!!
+
+
+
diff --git a/docs/_build/html/_sources/docs/app/usage.rst.txt b/docs/_build/html/_sources/docs/app/usage.rst.txt
new file mode 100644
index 0000000..7c44739
--- /dev/null
+++ b/docs/_build/html/_sources/docs/app/usage.rst.txt
@@ -0,0 +1,4 @@
+
+
+usage !!!
+======================
diff --git a/docs/_build/html/_sources/docs/guide/ansible/index.md.txt b/docs/_build/html/_sources/docs/guide/ansible/index.md.txt
new file mode 100644
index 0000000..c98bc9e
--- /dev/null
+++ b/docs/_build/html/_sources/docs/guide/ansible/index.md.txt
@@ -0,0 +1,12 @@
+# Ansible
+
+Topics:
+1) Apply role/profile pattern
+ * Mission: We want to apply to profile/class pattern to ansible inventories and playbooks.
+ * Always use dynamic inventories
+ * Static inventories are for shorthand aliases
+ * Design a simple tree
+ * Take advantages of this to generate dynamic ansible groups
+ * Use composed plugin
+ * THe power of ansible-tree
+ * Assign playbooks to specific roles
diff --git a/docs/_build/html/_sources/docs/guide/best_practices.md.txt b/docs/_build/html/_sources/docs/guide/best_practices.md.txt
new file mode 100644
index 0000000..28236a7
--- /dev/null
+++ b/docs/_build/html/_sources/docs/guide/best_practices.md.txt
@@ -0,0 +1,33 @@
+# Learn 104
+
+
+* 104: Best practices
+ - Going into IaC
+ + Use git to track your tree
+ - D.R.Y.
+ + Things are quite easily moving
+ - Code structure
+ + Profile and Class
+ * Role and profiles key lookup
+ + Hierarchies
+ * Foreman
+ + Use environnements, site, locatation ...
+ + Common keys vs dedicated keys
+ * The profile key, default placeholder
+ + The resource modele
+ * It's like a puppet resource, a catalog of items to apply
+ * It's possible to use this model with ansible, and it change radically the way Ansible can be used then. See integration.
+ - Debugging
+ + Use the explain mode
+ * And trace mode
+ + Use GNU tools
+ * tree
+ * grep -Rw .
+ * git status -sb
+ - With ansible.
+ + Use a strict naming scheme, apply your Ansible usual name schema into Kheops
+ + You can put some jinja variable into Kheops, Ansible will be able to replace and understand them during the runtime
+ + Dynamic inventories and ENC
+ + Apply products
+ + Apply roles/profiles pattern
+ + Use resource based roles => See my collection, it just works
diff --git a/docs/_build/html/_sources/docs/guide/index.rst.txt b/docs/_build/html/_sources/docs/guide/index.rst.txt
new file mode 100644
index 0000000..19f623f
--- /dev/null
+++ b/docs/_build/html/_sources/docs/guide/index.rst.txt
@@ -0,0 +1,10 @@
+
+Guides
+============
+
+
+.. toctree::
+ best_practices.md
+ ansible/index.md
+
+
diff --git a/docs/_build/html/_sources/docs/learn/100.rst.txt b/docs/_build/html/_sources/docs/learn/100.rst.txt
new file mode 100644
index 0000000..7f4d778
--- /dev/null
+++ b/docs/_build/html/_sources/docs/learn/100.rst.txt
@@ -0,0 +1,73 @@
+
+
+Introduction
+############
+
+This part introduce the concept of hierarchical lookups.
+
+
+.. contents:: Table of Contents
+
+
+.. note::
+
+ Note: This documentation has been partially taken and adapted from `Jerakia's Documentation `_
+
+
+Concept
+**************************
+
+In essence, Khéops is a tool that can be used to lookup a key value pair, that is to say, given a key it will give back the appropriate value. This is certainly nothing special or new, but the crucial difference here is the way in which the data is looked up. Rather than just querying a flat data source and returning the value for a requested key, when doing a hierarchical lookup we perform multiple queries against a configured hierarchy, transcending down to the next layer in the hierarchy until we find an answer. The end result is that we can define key value pairs on a global basis but then override them under certain conditions based on the hierarchical resolution by placing that key value pair further up the hierarchy for a particular condition.
+
+
+Hierarchical Lookups
+**************************
+
+Let’s look at a fairly simple example, you need to determine from a data lookup what currency you need to bill a user coming into your site. You already have data that tells you which country and continent that your user is based in. You determine that to start with you will bill everyone in USD regardless of where they come from. So you store the key currency with a value of USD in a data source somewhere, and whenever a user starts a transaction, you look up that key, and they get billed in USD
+
+Now comes the fun part. You decide that you would like to now start billing customers from European countries in EUR. Since you already know the continent your user is coming from you could add another key to your data store and then use conditional logic within your code to determine which key to look up, but now we’re adding complexity within the code implementing conditional logic to determine how to resolve the correct value. This is the very thing that hierarchical lookups aim to solve, to structure the data and perform the lookups in such a way that is transparent to the program requesting the data.
+
+Lets add another layer of complexity, you’ve agreed to use EUR for all users based in Europe, but you must now account for the UK and Switzerland which deal in GBP and CHF respectively, and potentially more. Now the demands for conditional logic on the program requesting the data are getting more complicated. To avoid lots of very convoluted conditional logic in your code you could simply map every country in the world to a currency and look up one key, that would be the cleanest method right now. But remember that we generally want to use USD for everyone and only care about changing this default under certain circumstances. If we think about this carefully, we have a hierarchy of importance. The country (in the case of UK or Switzerland), the continent in the case of Europe and then the rest of the world. This is where a hierarchical lookup simplifies the management of this data. The hierarchy we need to search here is quite simple;
+
+A hierarchy
+===============
+
+When we’re dealing with storing data for hierarchical searches, we end up with a tiered hierarchy that looks something like this. A lookup request to Khéops contains two things, they key that is being looked up, in this case “currency”, and some data about the context of the request which Khéops refers to as the scope. In this instance the scope contains the country and continent of the user. The scope and the key are used together, so when we are talking about hierarchical lookups, rather than just saying “return the value for this key” we are saying “return the value for this key in the context of this scope”. That’s the main distinction between a normal key value lookup and a hierarchical lookup. If you’re thinking of ways to do this in a structured query language (SQL) or some other database API, you might be ok to solve this problem - but this is a stripped down example looking up one value, now imagine we throw in tax parameters, shipping costs, and other fun things into the mix - this becomes a complex beast - but not when we think of this as a simple hierarchy.
+
+With a hierarchical data source we can declare a key value pair at the bottom level, in this case Worldwide. We can set that to USD, at this point any lookup request for the currency will return USD. But a hierarchical data source allows us to add a different value for the key “currency” at a different level of the hierarchy, for example we can add a value of EUR at the continent level that will only return that value if the continent is Europe. We can then add separate entries right at the top of the hierarchy for the UK and Switzerland, for requests where the country meets that criteria.
+
+From our program we are still making one lookup request for the data, but that data is looked up using a series of queries behind the scenes to resolve the right data. Essentially the lookup will trigger up to three queries. If one query doesn’t return an answer (because there is nothing specific configured in that level of the hierarchy) then it will fall back to the next level, and keep going until it hits an answer, eventually landing at the last level, Worldwide in our example. So a typical lookup for the currency of a user would be handled as;
+
+* What is the value for currency for this specific country?
+* What is the value for currency for this specific continent?
+* What is the value for currency for everything worldwide?
+
+Whichever level of the hierarchy responds first will win, meaning that if a user from China will get a value of USD - because we haven’t specified anything for Asia or China on the continent or country levels of the hierarchy so the lookup will fall through to our default set at the “worldwide” level. However, at the continent level of the hierarchy we specified an override of EUR for requests where the continent of the requestor is Europe, so users from Germany, France and Spain would get EUR. This wouldn’t be the case for the UK or Switzerland though because we’ve specifically overridden this at the country level, which is higher in the hierarchy so will win over the continent that the country belongs to.
+
+So hierarchical lookups are generally about defining a value at the widest possible catchment (eg: worldwide) and moving up the hierarchy overriding that value at the right level.
+
+What is key here is that rather than implementing three levels of conditional logic in our code, or mapping the lowest common denominator (country) one to one with currencies for every country in the world (remember in some cases we may not be able to identify the lowest common denominator) we have found a way to express the data in a simple way and provide one simple path to looking up the data. Our program still makes one request for the key currency, the logic involved in resolving the correct value is completely transparent.
+
+In this case, we had a scope (the country and continent of the requestor) and a hierarchy to search against that uses both elements of the scope and then falls back to a common catch all.
+
+
+Applying this to infrastructure management
+******************************************
+
+Khéops is standalone and can be used for any number of applications that can make use of a hierarchical type of data lookup, but it was originally built with configuration management in mind. Infrastructure data lends itself incredibly well to this model of data lookup. Infrastructure data tends to consist of any number of configurable attributes that are used to drive your infrastructure. These could be DNS resolvers, server hostnames, IP addresses, ports, API endpoints…. there is a ton of stuff that we configure on our infrastructures, but most of it is hierarchical. Generally speaking a lot of infrastructure data starts off with a baseline default, for example, what DNS resolver to use. That could be a default value thats used across the whole of your company and you add that as a key value pair to a datastore. Then you find yourself having to override that value for systems configured in your development environment because that environment can’t connect to the production resolvers on your network, you then may deploy your production environment out to a second data centre and you need that location to be different. But we are still dealing with simple hierarchies, so rather than programming conditionals to determine the resolution path of a DNS resolver we could build a simple hierarchy that best represents our infrastructure, such as;
+
+A hierarchy
+===============
+
+When dealing with a hierarchy like this, a data lookup must give us a key to lookup and contain a scope that tells us the hostname, environment and location of the request. Using the same principles as before our lookup will make up to 4 queries;
+
+ What is the DNS resolver for my particular hostname?
+ What is the DNS resolver for machines that are in my environment?
+ What is the DNS resolver for machines that are in my location?
+ What is the DNS resolver for everyone else?
+
+Again, this is hierarchical search pattern that will stop at the first query to return an answer and return that value. We can set our global parameters and then override them at the areas we care about. We’ve even got a top level hierarchy entry for that one edge case special snowflake server that is different from everything else on the network, but the lookup method is identical and transparent to the application requesting the data.
+Khéops
+
+This is a generic overview of hierarchical lookups, but in particular as they relate to Khéops. Khéops has way more features that build on top of this principle, like cascading lookups which don’t stop at the first result and will build a combined data structure (HashMap or Array) from all levels of the hierarchy and return a unified result based on the route taken through the hierarchy, and I’ll cover those in a follow up post. It’s also built to be extremely flexible and pluggable allowing you to source your data from pretty much anywhere and ships with an HTTP API meaning you can integrate Khéops with any tool regardless of the underlying language.
+
diff --git a/docs/_build/html/_sources/docs/learn/101.md.txt b/docs/_build/html/_sources/docs/learn/101.md.txt
new file mode 100644
index 0000000..f920ce2
--- /dev/null
+++ b/docs/_build/html/_sources/docs/learn/101.md.txt
@@ -0,0 +1,19 @@
+# Learn 101
+
+* 100: KEEPE IT SIMPLEME How works a hierarchical data lookup?
+ - Query a key
+ - Kheops is composed of 2 parts:
+ + It will first look in different locations the key. It is usually files, but it can also be an url or anything.
+ - Lookup data in a tree of files
+ + Goes sequentially according the backends list
+ * Backend/Engine list is modular
+ * Engine Plugin: Jerakia/HIera/Ansible/Curl
+ * Backend Plugin: loop/hier
+ + All result are returned, and then the rules are applied
+ + Rules match to a key and apply a strategy (essentially determine if and how the different value are merged or replaced). It can also apply filter to the result and modify its content (future).
+ * This is modular
+ * Strategy: last/schema
+ - Last will always take the last found value, whatever what it previously found.
+ - schema: It will take into account the strucutre of the data and try to merge them intelligentelly.
+ + Then it returns the result
+
diff --git a/docs/_build/html/_sources/docs/learn/102.md.txt b/docs/_build/html/_sources/docs/learn/102.md.txt
new file mode 100644
index 0000000..f766013
--- /dev/null
+++ b/docs/_build/html/_sources/docs/learn/102.md.txt
@@ -0,0 +1,21 @@
+# Learn 102
+
+* 102: Merging data
+
+ - Query on items/dicts
+ + With merge strategy
+ - Query on arrays/lists
+ + It appends, replace or what ?
+ - Query other types
+ - Query without key (!)
+ + Not the actual result, schema are not sub applied
+ * BUG: TO Fix ? Performance issue ?
+
+* 103: Scoped queries
+ - Add scoped variables
+ - Add variables to trees
+ - Use loops
+ - Use hierarchies, for hostgroups
+ - Use includes for other files (Future)
+
+
diff --git a/docs/_build/html/_sources/docs/learn/105.md.txt b/docs/_build/html/_sources/docs/learn/105.md.txt
new file mode 100644
index 0000000..c17547e
--- /dev/null
+++ b/docs/_build/html/_sources/docs/learn/105.md.txt
@@ -0,0 +1,8 @@
+# Learn 105
+
+* 105: Integrations
+ - Integration in Ansible
+ - Integration as a web server (future)
+ - Integration with Puppet
+ - Integration with Foreman
+
diff --git a/docs/_build/html/_sources/docs/learn/index.rst.txt b/docs/_build/html/_sources/docs/learn/index.rst.txt
new file mode 100644
index 0000000..5de2fdf
--- /dev/null
+++ b/docs/_build/html/_sources/docs/learn/index.rst.txt
@@ -0,0 +1,17 @@
+
+
+Learn
+===========
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ ../../learn/learn101.md
+ 100.rst
+ 101.md
+ 102.md
+ 105.md
+
+
+Learning resources
diff --git a/docs/_build/html/_sources/index.rst.txt b/docs/_build/html/_sources/index.rst.txt
new file mode 100644
index 0000000..f2f7d80
--- /dev/null
+++ b/docs/_build/html/_sources/index.rst.txt
@@ -0,0 +1,43 @@
+
+
+.. image:: ../logo/kheops_brand.png
+ :target: https://amoffat.github.com/sh
+ :alt: Logo
+
+
+Khéops documentation
+=======================================================
+
+.. contents:: Table of Contents
+
+.. currentmodule:: kheops
+
+
+Welcome in Khéops documentation.
+
+
+Khéops is a tool that can be used to lookup a key value pair, that is to say, given a key it will give back the appropriate value. This is certainly nothing special or new, but the crucial difference here is the way in which the data is looked up. Rather than just querying a flat data source and returning the value for a requested key, when doing a hierarchical lookup we perform multiple queries against a configured hierarchy, transcending down to the next layer in the hierarchy until we find an answer. The end result is that we can define key value pairs on a global basis but then override them under certain conditions based on the hierarchical resolution by placing that key value pair further up the hierarchy for a particular condition.
+
+
+
+Content
+==================
+
+.. toctree::
+ :maxdepth: 3
+ :caption: Contents:
+ :glob:
+
+ docs/app/index.rst
+ docs/learn/index.rst
+ docs/guide/index.rst
+ Python API
+
+
+Indices and tables
+==================
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
+
diff --git a/docs/_build/html/_sources/learn/learn101.md.txt b/docs/_build/html/_sources/learn/learn101.md.txt
new file mode 100644
index 0000000..9527a87
--- /dev/null
+++ b/docs/_build/html/_sources/learn/learn101.md.txt
@@ -0,0 +1,799 @@
+# Khéops 101
+
+
+```bash
+cd /home/jez/volumes/data/prj/bell/training/tiger-ansible/ext/kheops
+echo $PWD
+export KHEOPS_NAMESPACE=ex1_enc
+export KHEOPS_CONFIG=examples/kheops.yml
+rm -rf "examples/$KHEOPS_NAMESPACE"
+```
+
+ /home/jez/volumes/data/prj/bell/training/tiger-ansible/ext/kheops
+
+
+## Command line
+
+Let's check first that kheops works correclty, and start to read the manual.
+
+
+```bash
+kheops --help
+```
+
+ usage: kheops [-h] [-v] [-c CONFIG]
+ {schema,gen_doc,lookup,demo,subcommand2} ...
+
+ Kheops, hierarchical data lookup tool
+
+ options:
+ -h, --help show this help message and exit
+ -v, --verbose Increase verbosity (KHEOPS_VERBOSE) (default: 0)
+ -c CONFIG, --config CONFIG
+ Kheops configuration file (KHEOPS_CONFIG) (default:
+ examples/kheops.yml)
+
+ subcommands:
+ valid subcommands
+
+ {schema,gen_doc,lookup,demo,subcommand2}
+
+
+So we have a working `kheops` command, and we will focus on the `lookup` command. On it's simplest form, a lookup consists in querying a `key` for a given `scope`. The output of the `key` will change depending the `scope` value. A `key` is in simple word.
+
+## Defining a hierarchy
+
+To illustrate how Khéops works, let's start with a simple example, we will try to lookup the `profile` key of the following two (fictive) servers:
+
+* web.domain.org: which act as a webserver role
+* mysql.domain.org: which act as mysql role
+
+But first we need to create our hierarchy. It's as simple as creating directories and put some json or yaml data into different files. Let's create our hierarchy. We will first create the default profile:
+
+
+From our use case, we will build a lookup tree. We want to be able to organise data depending the 3 criterias:
+
+* node: name of the node
+* role: assigned role to the node
+* environment: it can either be dev or prod
+
+Let's create our lookup hierarchy:
+
+default:
+ lookups:
+ - path: default # Simplest form, just a path
+ - path: "roles/{role}" # If list, it's auto expanded like in bash
+ - path: "env_{env}" # If list, it's auto expanded like in bash
+ - path: "nodes/{node}"
+
+
+So for a given key, Khéops will iterate all over those paths to find the requested `key` , and then it will merge all results. Some paths are variabilized, and those variable comes from the scope. The scope come along the `key`, it's can be any metadata. For complex metadata you may want to store those in a file and load your scope with the `-f ` option:
+
+```
+kheops lookup -e -e
+```
+
+A scope is completely optional while keys are required.
+
+
+```bash
+
+```
+
+## Basic hierarchy
+
+
+```bash
+# We create a fresh hierachy
+mkdir -p examples/$KHEOPS_NAMESPACE
+
+# We create a profile key, which is a dict
+cat > examples/$KHEOPS_NAMESPACE/default.yml < examples/$KHEOPS_NAMESPACE/roles/web.yml < examples/$KHEOPS_NAMESPACE/roles/mysql.yml < examples/ex1_enc/default.yml <==
+ ---
+ profile:
+ env: "NO_ENV"
+ product: "NO_PRODUCT"
+
+
+ ==> examples/ex1_enc/roles/mysql.yml <==
+ ---
+ profile:
+ product: "mysql_server"
+
+ mysql_database: "NO_DATABASE"
+ mysql_users:
+ - "sysadmin@10.0.42%"
+ mysql_port: 3306
+ mysql_cluster: False
+
+
+ ==> examples/ex1_enc/roles/web.yml <==
+ ---
+ profile:
+ product: "httpd_server"
+
+ web_top_domain: ""
+ web_app: "NO_APP"
+ web_port: 80
+ web_user_list:
+ - sysadmins
+
+
+
+
+```bash
+kheops lookup -e node=web.infra.net -e role=web profile
+kheops lookup -e node=mysql.infra.net -e role=mysql profile
+```
+
+ env: NO_ENV
+ product: httpd_server
+ web_top_domain: ''
+ web_app: NO_APP
+ web_port: 80
+ web_user_list:
+ - sysadmins
+
+ env: NO_ENV
+ product: mysql_server
+ mysql_database: NO_DATABASE
+ mysql_users:
+ - sysadmin@10.0.42%
+ mysql_port: 3306
+ mysql_cluster: false
+
+
+
+## Per node override
+
+It's getting better, we can see that the profile key has been merged with the key values, across the different locations.
+
+However, we will have those placeholders, and we want to have personalized value, depending if it's aweb server, it need an unique domain and some unique parameters. So let's create a `nodes` directory and place some data inside.
+
+
+
+
+```bash
+mkdir -p examples/$KHEOPS_NAMESPACE/nodes
+
+# We create a new web role
+cat > examples/$KHEOPS_NAMESPACE/nodes/web.infra.net.yml < examples/$KHEOPS_NAMESPACE/nodes/mysql.infra.net.yml < examples/$KHEOPS_NAMESPACE/env_dev.yml < examples/$KHEOPS_NAMESPACE/env_prod.yml < Per environment view"
+kheops lookup -e env=prod profile
+kheops lookup -e env=dev profile
+
+echo "==> Per role and environment view"
+kheops lookup -e role=mysql -e env=prod profile
+kheops lookup -e role=web -e env=prod profile
+
+echo "==> Per node view"
+kheops lookup -e node=web.infra.net -e role=web -e env=dev profile
+```
+
+ env: NO_ENV
+ product: NO_PRODUCT
+
+ ==> Per environment view
+ env: prod
+ product: NO_PRODUCT
+ web_top_domain: infra.com
+ web_cache: 12h
+
+ env: dev
+ product: NO_PRODUCT
+ web_top_domain: dev.infra.net
+ web_cache: 1m
+ web_user_list:
+ - debug_user
+ mysql_users:
+ - debug@10.0.%
+ debug: true
+
+ ==> Per role and environment view
+ env: prod
+ product: mysql_server
+ mysql_database: NO_DATABASE
+ mysql_users:
+ - sysadmin@10.0.42%
+ mysql_port: 3306
+ mysql_cluster: false
+ web_top_domain: infra.com
+ web_cache: 12h
+
+ env: prod
+ product: httpd_server
+ web_top_domain: infra.com
+ web_app: NO_APP
+ web_port: 80
+ web_user_list:
+ - sysadmins
+ web_cache: 12h
+
+ ==> Per node view
+ env: dev
+ product: httpd_server
+ web_top_domain: dev.infra.net
+ web_app: myapp
+ web_port: 80
+ web_user_list:
+ - sysadmins
+ - debug_user
+ - domain_org
+ - domain_org_external
+ web_cache: 1m
+ mysql_users:
+ - debug@10.0.%
+ debug: true
+
+
+
+Even if somwaht clunky, this method can help to troubleshoot wrong data by dichotomy.
+
+
+```bash
+
+```
+
+## Tooling and applications
+
+
+```bash
+
+```
+
+
+```bash
+
+```
+
+
+```bash
+
+```
+
+
+```bash
+
+```
+
+
+```bash
+
+```
+
+## Troubleshooting
+
+Sometimes, it can may be hard to navigate across file and hierachy, but GNU Utils are here to help. There is a selection of small tips:
+
+
+```bash
+set -x
+
+: Find where a key has been defined
+grep -r '^profile:' examples/$KHEOPS_NAMESPACE
+
+: Find where a key has been defined and 5 first lines
+grep -r -A 5 'web_user_list:' examples/$KHEOPS_NAMESPACE
+
+: Search from anything related to database
+grep -R -C 3 'database' examples/$KHEOPS_NAMESPACE
+
+set +x
+```
+
+ + : Find where a key has been defined
+ + grep --colour=auto -r '^profile:' examples/ex1_enc
+ [35m[Kexamples/ex1_enc/env_prod.yml[m[K[36m[K:[m[K[01;31m[Kprofile:[m[K
+ [35m[Kexamples/ex1_enc/roles/mysql.yml[m[K[36m[K:[m[K[01;31m[Kprofile:[m[K
+ [35m[Kexamples/ex1_enc/roles/web.yml[m[K[36m[K:[m[K[01;31m[Kprofile:[m[K
+ [35m[Kexamples/ex1_enc/nodes/mysql.infra.net.yml[m[K[36m[K:[m[K[01;31m[Kprofile:[m[K
+ [35m[Kexamples/ex1_enc/nodes/web.infra.net.yml[m[K[36m[K:[m[K[01;31m[Kprofile:[m[K
+ [35m[Kexamples/ex1_enc/default.yml[m[K[36m[K:[m[K[01;31m[Kprofile:[m[K
+ [35m[Kexamples/ex1_enc/env_dev.yml[m[K[36m[K:[m[K[01;31m[Kprofile:[m[K
+ + : Find where a key has been defined and 5 first lines
+ + grep --colour=auto -r -A 5 web_user_list: examples/ex1_enc
+ [35m[Kexamples/ex1_enc/roles/web.yml[m[K[36m[K:[m[K [01;31m[Kweb_user_list:[m[K
+ [35m[Kexamples/ex1_enc/roles/web.yml[m[K[36m[K-[m[K - sysadmins
+ [35m[Kexamples/ex1_enc/roles/web.yml[m[K[36m[K-[m[K
+ [36m[K--[m[K
+ [35m[Kexamples/ex1_enc/nodes/web.infra.net.yml[m[K[36m[K:[m[K [01;31m[Kweb_user_list:[m[K
+ [35m[Kexamples/ex1_enc/nodes/web.infra.net.yml[m[K[36m[K-[m[K - domain_org
+ [35m[Kexamples/ex1_enc/nodes/web.infra.net.yml[m[K[36m[K-[m[K - domain_org_external
+ [35m[Kexamples/ex1_enc/nodes/web.infra.net.yml[m[K[36m[K-[m[K
+ [36m[K--[m[K
+ [35m[Kexamples/ex1_enc/env_dev.yml[m[K[36m[K:[m[K [01;31m[Kweb_user_list:[m[K
+ [35m[Kexamples/ex1_enc/env_dev.yml[m[K[36m[K-[m[K - debug_user
+ [35m[Kexamples/ex1_enc/env_dev.yml[m[K[36m[K-[m[K mysql_users:
+ [35m[Kexamples/ex1_enc/env_dev.yml[m[K[36m[K-[m[K - debug@10.0.%
+ [35m[Kexamples/ex1_enc/env_dev.yml[m[K[36m[K-[m[K
+ [35m[Kexamples/ex1_enc/env_dev.yml[m[K[36m[K-[m[K debug: true
+ + : Search from anything related to database
+ + grep --colour=auto -R -C 3 database examples/ex1_enc
+ [35m[Kexamples/ex1_enc/roles/mysql.yml[m[K[36m[K-[m[Kprofile:
+ [35m[Kexamples/ex1_enc/roles/mysql.yml[m[K[36m[K-[m[K product: "mysql_server"
+ [35m[Kexamples/ex1_enc/roles/mysql.yml[m[K[36m[K-[m[K
+ [35m[Kexamples/ex1_enc/roles/mysql.yml[m[K[36m[K:[m[K mysql_[01;31m[Kdatabase[m[K: "NO_DATABASE"
+ [35m[Kexamples/ex1_enc/roles/mysql.yml[m[K[36m[K-[m[K mysql_users:
+ [35m[Kexamples/ex1_enc/roles/mysql.yml[m[K[36m[K-[m[K - "sysadmin@10.0.42%"
+ [35m[Kexamples/ex1_enc/roles/mysql.yml[m[K[36m[K-[m[K mysql_port: 3306
+ [36m[K--[m[K
+ [35m[Kexamples/ex1_enc/nodes/mysql.infra.net.yml[m[K[36m[K-[m[K---
+ [35m[Kexamples/ex1_enc/nodes/mysql.infra.net.yml[m[K[36m[K-[m[Kprofile:
+ [35m[Kexamples/ex1_enc/nodes/mysql.infra.net.yml[m[K[36m[K:[m[K mysql_[01;31m[Kdatabase[m[K: "app_domain_org"
+ [35m[Kexamples/ex1_enc/nodes/mysql.infra.net.yml[m[K[36m[K-[m[K mysql_users:
+ [35m[Kexamples/ex1_enc/nodes/mysql.infra.net.yml[m[K[36m[K-[m[K - "app_domain_org@10.0.51%"
+ [35m[Kexamples/ex1_enc/nodes/mysql.infra.net.yml[m[K[36m[K-[m[K
+ + set +x
+
+
+
+```bash
+
+```
+
+The tail/head command is quite usefull to look at multiple files at the same time, it add a nice header for each file:
+
+
+```bash
+head -n 999 examples/ex1_enc/roles/*
+```
+
+ ==> examples/ex1_enc/roles/mysql.yml <==
+ ---
+ profile:
+ product: "mysql_server"
+
+ mysql_database: "NO_DATABASE"
+ mysql_users:
+ - "sysadmin@10.0.42%"
+ mysql_port: 3306
+ mysql_cluster: False
+
+
+ ==> examples/ex1_enc/roles/web.yml <==
+ ---
+ profile:
+ product: "httpd_server"
+
+ web_top_domain: ""
+ web_app: "NO_APP"
+ web_port: 80
+ web_user_list:
+ - sysadmins
+
+
+
+You can also have a view of all files with this command:
+```
+find . -type f| xargs head -n 999 | less
+```
+
+From there, you will be able to have a nice overview of your data.
+
+You can even diff your change with this command. There is this simple trick to compare the data difference between 2 lookups:
+
+
+```bash
+diff -u \
+<(kheops lookup -e node=web.infra.net -e role=web -e env=prod profile) \
+<(kheops lookup -e node=web.infra.net -e role=web -e env=dev profile)
+```
+
+ --- /dev/fd/63 2022-02-01 20:10:53.094525316 -0500
+ +++ /dev/fd/62 2022-02-01 20:10:53.094525316 -0500
+ @@ -1,11 +1,15 @@
+ -env: prod
+ +env: dev
+ product: httpd_server
+ -web_top_domain: infra.com
+ +web_top_domain: dev.infra.net
+ web_app: myapp
+ web_port: 80
+ web_user_list:
+ - sysadmins
+ +- debug_user
+ - domain_org
+ - domain_org_external
+ -web_cache: 12h
+ +web_cache: 1m
+ +mysql_users:
+ +- debug@10.0.%
+ +debug: true
+
+
+
+
+
+
+```bash
+
+```
+
+You can also ask Kheops to explain you how he built the result, you can use the `-x` flag:
+
+
+```bash
+kheops lookup -e role=web profile -x
+```
+
+ INFO: Explain lookups:
+ +------------------------+------------------------------+
+ | Config | Runtime |
+ +------------------------+------------------------------+
+ | | |
+ | Config:{ | Runtime:{ |
+ | "path": "default", | "scope": { |
+ | "backend": "file", | "role": "web" |
+ | "continue": true | }, |
+ | } | "key": "profile", |
+ | | "conf": { |
+ | | "index": 0 |
+ | | }, |
+ | | "raw_path": "default" |
+ | | } |
+ | | |
+ | Config:{ | Runtime:{ |
+ | "path": "roles/web", | "scope": { |
+ | "backend": "file", | "role": "web" |
+ | "continue": true | }, |
+ | } | "key": "profile", |
+ | | "conf": { |
+ | | "index": 1 |
+ | | }, |
+ | | "raw_path": "roles/{role}" |
+ | | } |
+ +------------------------+------------------------------+
+ INFO: Explain candidates:
+ +----------------------------------------------------------------------------------+-------------------------------+------------------------------+
+ | Status | Runtime | Data |
+ +----------------------------------------------------------------------------------+-------------------------------+------------------------------+
+ | | | |
+ | Status:{ | Runtime:{ | Data:{ |
+ | "path": "/home/jez/volumes/data/prj/bell/training/tiger-ansible/ext/kheops ... | "scope": { | "env": "NO_ENV", |
+ | "status": "found", | "role": "web" | "product": "NO_PRODUCT" |
+ | "rel_path": "examples/ex1_enc/default.yml" | }, | } |
+ | } | "key": "profile", | |
+ | | "conf": { | |
+ | | "index": 0 | |
+ | | }, | |
+ | | "raw_path": "default", | |
+ | | "backend_index": 0 | |
+ | | } | |
+ | | | |
+ | Status:{ | Runtime:{ | Data:{ |
+ | "path": "/home/jez/volumes/data/prj/bell/training/tiger-ansible/ext/kheops ... | "scope": { | "product": "httpd_server", |
+ | "status": "found", | "role": "web" | "web_top_domain": "", |
+ | "rel_path": "examples/ex1_enc/roles/web.yml" | }, | "web_app": "NO_APP", |
+ | } | "key": "profile", | "web_port": 80, |
+ | | "conf": { | "web_user_list": [ |
+ | | "index": 1 | "sysadmins" |
+ | | }, | ] |
+ | | "raw_path": "roles/{role}", | } |
+ | | "backend_index": 1 | |
+ | | } | |
+ +----------------------------------------------------------------------------------+-------------------------------+------------------------------+
+ env: NO_ENV
+ product: httpd_server
+ web_top_domain: ''
+ web_app: NO_APP
+ web_port: 80
+ web_user_list:
+ - sysadmins
+
+
+
+
+```bash
+
+```
diff --git a/docs/_build/html/_static/alabaster.css b/docs/_build/html/_static/alabaster.css
new file mode 100644
index 0000000..0eddaeb
--- /dev/null
+++ b/docs/_build/html/_static/alabaster.css
@@ -0,0 +1,701 @@
+@import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+ font-family: Georgia, serif;
+ font-size: 17px;
+ background-color: #fff;
+ color: #000;
+ margin: 0;
+ padding: 0;
+}
+
+
+div.document {
+ width: 940px;
+ margin: 30px auto 0 auto;
+}
+
+div.documentwrapper {
+ float: left;
+ width: 100%;
+}
+
+div.bodywrapper {
+ margin: 0 0 0 220px;
+}
+
+div.sphinxsidebar {
+ width: 220px;
+ font-size: 14px;
+ line-height: 1.5;
+}
+
+hr {
+ border: 1px solid #B1B4B6;
+}
+
+div.body {
+ background-color: #fff;
+ color: #3E4349;
+ padding: 0 30px 0 30px;
+}
+
+div.body > .section {
+ text-align: left;
+}
+
+div.footer {
+ width: 940px;
+ margin: 20px auto 30px auto;
+ font-size: 14px;
+ color: #888;
+ text-align: right;
+}
+
+div.footer a {
+ color: #888;
+}
+
+p.caption {
+ font-family: inherit;
+ font-size: inherit;
+}
+
+
+div.relations {
+ display: none;
+}
+
+
+div.sphinxsidebar a {
+ color: #444;
+ text-decoration: none;
+ border-bottom: 1px dotted #999;
+}
+
+div.sphinxsidebar a:hover {
+ border-bottom: 1px solid #999;
+}
+
+div.sphinxsidebarwrapper {
+ padding: 18px 10px;
+}
+
+div.sphinxsidebarwrapper p.logo {
+ padding: 0;
+ margin: -10px 0 0 0px;
+ text-align: center;
+}
+
+div.sphinxsidebarwrapper h1.logo {
+ margin-top: -10px;
+ text-align: center;
+ margin-bottom: 5px;
+ text-align: left;
+}
+
+div.sphinxsidebarwrapper h1.logo-name {
+ margin-top: 0px;
+}
+
+div.sphinxsidebarwrapper p.blurb {
+ margin-top: 0;
+ font-style: normal;
+}
+
+div.sphinxsidebar h3,
+div.sphinxsidebar h4 {
+ font-family: Georgia, serif;
+ color: #444;
+ font-size: 24px;
+ font-weight: normal;
+ margin: 0 0 5px 0;
+ padding: 0;
+}
+
+div.sphinxsidebar h4 {
+ font-size: 20px;
+}
+
+div.sphinxsidebar h3 a {
+ color: #444;
+}
+
+div.sphinxsidebar p.logo a,
+div.sphinxsidebar h3 a,
+div.sphinxsidebar p.logo a:hover,
+div.sphinxsidebar h3 a:hover {
+ border: none;
+}
+
+div.sphinxsidebar p {
+ color: #555;
+ margin: 10px 0;
+}
+
+div.sphinxsidebar ul {
+ margin: 10px 0;
+ padding: 0;
+ color: #000;
+}
+
+div.sphinxsidebar ul li.toctree-l1 > a {
+ font-size: 120%;
+}
+
+div.sphinxsidebar ul li.toctree-l2 > a {
+ font-size: 110%;
+}
+
+div.sphinxsidebar input {
+ border: 1px solid #CCC;
+ font-family: Georgia, serif;
+ font-size: 1em;
+}
+
+div.sphinxsidebar hr {
+ border: none;
+ height: 1px;
+ color: #AAA;
+ background: #AAA;
+
+ text-align: left;
+ margin-left: 0;
+ width: 50%;
+}
+
+div.sphinxsidebar .badge {
+ border-bottom: none;
+}
+
+div.sphinxsidebar .badge:hover {
+ border-bottom: none;
+}
+
+/* To address an issue with donation coming after search */
+div.sphinxsidebar h3.donation {
+ margin-top: 10px;
+}
+
+/* -- body styles ----------------------------------------------------------- */
+
+a {
+ color: #004B6B;
+ text-decoration: underline;
+}
+
+a:hover {
+ color: #6D4100;
+ text-decoration: underline;
+}
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+ font-family: Georgia, serif;
+ font-weight: normal;
+ margin: 30px 0px 10px 0px;
+ padding: 0;
+}
+
+div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
+div.body h2 { font-size: 180%; }
+div.body h3 { font-size: 150%; }
+div.body h4 { font-size: 130%; }
+div.body h5 { font-size: 100%; }
+div.body h6 { font-size: 100%; }
+
+a.headerlink {
+ color: #DDD;
+ padding: 0 4px;
+ text-decoration: none;
+}
+
+a.headerlink:hover {
+ color: #444;
+ background: #EAEAEA;
+}
+
+div.body p, div.body dd, div.body li {
+ line-height: 1.4em;
+}
+
+div.admonition {
+ margin: 20px 0px;
+ padding: 10px 30px;
+ background-color: #EEE;
+ border: 1px solid #CCC;
+}
+
+div.admonition tt.xref, div.admonition code.xref, div.admonition a tt {
+ background-color: #FBFBFB;
+ border-bottom: 1px solid #fafafa;
+}
+
+div.admonition p.admonition-title {
+ font-family: Georgia, serif;
+ font-weight: normal;
+ font-size: 24px;
+ margin: 0 0 10px 0;
+ padding: 0;
+ line-height: 1;
+}
+
+div.admonition p.last {
+ margin-bottom: 0;
+}
+
+div.highlight {
+ background-color: #fff;
+}
+
+dt:target, .highlight {
+ background: #FAF3E8;
+}
+
+div.warning {
+ background-color: #FCC;
+ border: 1px solid #FAA;
+}
+
+div.danger {
+ background-color: #FCC;
+ border: 1px solid #FAA;
+ -moz-box-shadow: 2px 2px 4px #D52C2C;
+ -webkit-box-shadow: 2px 2px 4px #D52C2C;
+ box-shadow: 2px 2px 4px #D52C2C;
+}
+
+div.error {
+ background-color: #FCC;
+ border: 1px solid #FAA;
+ -moz-box-shadow: 2px 2px 4px #D52C2C;
+ -webkit-box-shadow: 2px 2px 4px #D52C2C;
+ box-shadow: 2px 2px 4px #D52C2C;
+}
+
+div.caution {
+ background-color: #FCC;
+ border: 1px solid #FAA;
+}
+
+div.attention {
+ background-color: #FCC;
+ border: 1px solid #FAA;
+}
+
+div.important {
+ background-color: #EEE;
+ border: 1px solid #CCC;
+}
+
+div.note {
+ background-color: #EEE;
+ border: 1px solid #CCC;
+}
+
+div.tip {
+ background-color: #EEE;
+ border: 1px solid #CCC;
+}
+
+div.hint {
+ background-color: #EEE;
+ border: 1px solid #CCC;
+}
+
+div.seealso {
+ background-color: #EEE;
+ border: 1px solid #CCC;
+}
+
+div.topic {
+ background-color: #EEE;
+}
+
+p.admonition-title {
+ display: inline;
+}
+
+p.admonition-title:after {
+ content: ":";
+}
+
+pre, tt, code {
+ font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+ font-size: 0.9em;
+}
+
+.hll {
+ background-color: #FFC;
+ margin: 0 -12px;
+ padding: 0 12px;
+ display: block;
+}
+
+img.screenshot {
+}
+
+tt.descname, tt.descclassname, code.descname, code.descclassname {
+ font-size: 0.95em;
+}
+
+tt.descname, code.descname {
+ padding-right: 0.08em;
+}
+
+img.screenshot {
+ -moz-box-shadow: 2px 2px 4px #EEE;
+ -webkit-box-shadow: 2px 2px 4px #EEE;
+ box-shadow: 2px 2px 4px #EEE;
+}
+
+table.docutils {
+ border: 1px solid #888;
+ -moz-box-shadow: 2px 2px 4px #EEE;
+ -webkit-box-shadow: 2px 2px 4px #EEE;
+ box-shadow: 2px 2px 4px #EEE;
+}
+
+table.docutils td, table.docutils th {
+ border: 1px solid #888;
+ padding: 0.25em 0.7em;
+}
+
+table.field-list, table.footnote {
+ border: none;
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+
+table.footnote {
+ margin: 15px 0;
+ width: 100%;
+ border: 1px solid #EEE;
+ background: #FDFDFD;
+ font-size: 0.9em;
+}
+
+table.footnote + table.footnote {
+ margin-top: -15px;
+ border-top: none;
+}
+
+table.field-list th {
+ padding: 0 0.8em 0 0;
+}
+
+table.field-list td {
+ padding: 0;
+}
+
+table.field-list p {
+ margin-bottom: 0.8em;
+}
+
+/* Cloned from
+ * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68
+ */
+.field-name {
+ -moz-hyphens: manual;
+ -ms-hyphens: manual;
+ -webkit-hyphens: manual;
+ hyphens: manual;
+}
+
+table.footnote td.label {
+ width: .1px;
+ padding: 0.3em 0 0.3em 0.5em;
+}
+
+table.footnote td {
+ padding: 0.3em 0.5em;
+}
+
+dl {
+ margin: 0;
+ padding: 0;
+}
+
+dl dd {
+ margin-left: 30px;
+}
+
+blockquote {
+ margin: 0 0 0 30px;
+ padding: 0;
+}
+
+ul, ol {
+ /* Matches the 30px from the narrow-screen "li > ul" selector below */
+ margin: 10px 0 10px 30px;
+ padding: 0;
+}
+
+pre {
+ background: #EEE;
+ padding: 7px 30px;
+ margin: 15px 0px;
+ line-height: 1.3em;
+}
+
+div.viewcode-block:target {
+ background: #ffd;
+}
+
+dl pre, blockquote pre, li pre {
+ margin-left: 0;
+ padding-left: 30px;
+}
+
+tt, code {
+ background-color: #ecf0f3;
+ color: #222;
+ /* padding: 1px 2px; */
+}
+
+tt.xref, code.xref, a tt {
+ background-color: #FBFBFB;
+ border-bottom: 1px solid #fff;
+}
+
+a.reference {
+ text-decoration: none;
+ border-bottom: 1px dotted #004B6B;
+}
+
+/* Don't put an underline on images */
+a.image-reference, a.image-reference:hover {
+ border-bottom: none;
+}
+
+a.reference:hover {
+ border-bottom: 1px solid #6D4100;
+}
+
+a.footnote-reference {
+ text-decoration: none;
+ font-size: 0.7em;
+ vertical-align: top;
+ border-bottom: 1px dotted #004B6B;
+}
+
+a.footnote-reference:hover {
+ border-bottom: 1px solid #6D4100;
+}
+
+a:hover tt, a:hover code {
+ background: #EEE;
+}
+
+
+@media screen and (max-width: 870px) {
+
+ div.sphinxsidebar {
+ display: none;
+ }
+
+ div.document {
+ width: 100%;
+
+ }
+
+ div.documentwrapper {
+ margin-left: 0;
+ margin-top: 0;
+ margin-right: 0;
+ margin-bottom: 0;
+ }
+
+ div.bodywrapper {
+ margin-top: 0;
+ margin-right: 0;
+ margin-bottom: 0;
+ margin-left: 0;
+ }
+
+ ul {
+ margin-left: 0;
+ }
+
+ li > ul {
+ /* Matches the 30px from the "ul, ol" selector above */
+ margin-left: 30px;
+ }
+
+ .document {
+ width: auto;
+ }
+
+ .footer {
+ width: auto;
+ }
+
+ .bodywrapper {
+ margin: 0;
+ }
+
+ .footer {
+ width: auto;
+ }
+
+ .github {
+ display: none;
+ }
+
+
+
+}
+
+
+
+@media screen and (max-width: 875px) {
+
+ body {
+ margin: 0;
+ padding: 20px 30px;
+ }
+
+ div.documentwrapper {
+ float: none;
+ background: #fff;
+ }
+
+ div.sphinxsidebar {
+ display: block;
+ float: none;
+ width: 102.5%;
+ margin: 50px -30px -20px -30px;
+ padding: 10px 20px;
+ background: #333;
+ color: #FFF;
+ }
+
+ div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p,
+ div.sphinxsidebar h3 a {
+ color: #fff;
+ }
+
+ div.sphinxsidebar a {
+ color: #AAA;
+ }
+
+ div.sphinxsidebar p.logo {
+ display: none;
+ }
+
+ div.document {
+ width: 100%;
+ margin: 0;
+ }
+
+ div.footer {
+ display: none;
+ }
+
+ div.bodywrapper {
+ margin: 0;
+ }
+
+ div.body {
+ min-height: 0;
+ padding: 0;
+ }
+
+ .rtd_doc_footer {
+ display: none;
+ }
+
+ .document {
+ width: auto;
+ }
+
+ .footer {
+ width: auto;
+ }
+
+ .footer {
+ width: auto;
+ }
+
+ .github {
+ display: none;
+ }
+}
+
+
+/* misc. */
+
+.revsys-inline {
+ display: none!important;
+}
+
+/* Make nested-list/multi-paragraph items look better in Releases changelog
+ * pages. Without this, docutils' magical list fuckery causes inconsistent
+ * formatting between different release sub-lists.
+ */
+div#changelog > div.section > ul > li > p:only-child {
+ margin-bottom: 0;
+}
+
+/* Hide fugly table cell borders in ..bibliography:: directive output */
+table.docutils.citation, table.docutils.citation td, table.docutils.citation th {
+ border: none;
+ /* Below needed in some edge cases; if not applied, bottom shadows appear */
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+
+
+/* relbar */
+
+.related {
+ line-height: 30px;
+ width: 100%;
+ font-size: 0.9rem;
+}
+
+.related.top {
+ border-bottom: 1px solid #EEE;
+ margin-bottom: 20px;
+}
+
+.related.bottom {
+ border-top: 1px solid #EEE;
+}
+
+.related ul {
+ padding: 0;
+ margin: 0;
+ list-style: none;
+}
+
+.related li {
+ display: inline;
+}
+
+nav#rellinks {
+ float: right;
+}
+
+nav#rellinks li+li:before {
+ content: "|";
+}
+
+nav#breadcrumbs li+li:before {
+ content: "\00BB";
+}
+
+/* Hide certain items when printing */
+@media print {
+ div.related {
+ display: none;
+ }
+}
\ No newline at end of file
diff --git a/docs/_build/html/_static/basic.css b/docs/_build/html/_static/basic.css
new file mode 100644
index 0000000..bf18350
--- /dev/null
+++ b/docs/_build/html/_static/basic.css
@@ -0,0 +1,906 @@
+/*
+ * basic.css
+ * ~~~~~~~~~
+ *
+ * Sphinx stylesheet -- basic theme.
+ *
+ * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/* -- main layout ----------------------------------------------------------- */
+
+div.clearer {
+ clear: both;
+}
+
+div.section::after {
+ display: block;
+ content: '';
+ clear: left;
+}
+
+/* -- relbar ---------------------------------------------------------------- */
+
+div.related {
+ width: 100%;
+ font-size: 90%;
+}
+
+div.related h3 {
+ display: none;
+}
+
+div.related ul {
+ margin: 0;
+ padding: 0 0 0 10px;
+ list-style: none;
+}
+
+div.related li {
+ display: inline;
+}
+
+div.related li.right {
+ float: right;
+ margin-right: 5px;
+}
+
+/* -- sidebar --------------------------------------------------------------- */
+
+div.sphinxsidebarwrapper {
+ padding: 10px 5px 0 10px;
+}
+
+div.sphinxsidebar {
+ float: left;
+ width: 230px;
+ margin-left: -100%;
+ font-size: 90%;
+ word-wrap: break-word;
+ overflow-wrap : break-word;
+}
+
+div.sphinxsidebar ul {
+ list-style: none;
+}
+
+div.sphinxsidebar ul ul,
+div.sphinxsidebar ul.want-points {
+ margin-left: 20px;
+ list-style: square;
+}
+
+div.sphinxsidebar ul ul {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+div.sphinxsidebar form {
+ margin-top: 10px;
+}
+
+div.sphinxsidebar input {
+ border: 1px solid #98dbcc;
+ font-family: sans-serif;
+ font-size: 1em;
+}
+
+div.sphinxsidebar #searchbox form.search {
+ overflow: hidden;
+}
+
+div.sphinxsidebar #searchbox input[type="text"] {
+ float: left;
+ width: 80%;
+ padding: 0.25em;
+ box-sizing: border-box;
+}
+
+div.sphinxsidebar #searchbox input[type="submit"] {
+ float: left;
+ width: 20%;
+ border-left: none;
+ padding: 0.25em;
+ box-sizing: border-box;
+}
+
+
+img {
+ border: 0;
+ max-width: 100%;
+}
+
+/* -- search page ----------------------------------------------------------- */
+
+ul.search {
+ margin: 10px 0 0 20px;
+ padding: 0;
+}
+
+ul.search li {
+ padding: 5px 0 5px 20px;
+ background-image: url(file.png);
+ background-repeat: no-repeat;
+ background-position: 0 7px;
+}
+
+ul.search li a {
+ font-weight: bold;
+}
+
+ul.search li p.context {
+ color: #888;
+ margin: 2px 0 0 30px;
+ text-align: left;
+}
+
+ul.keywordmatches li.goodmatch a {
+ font-weight: bold;
+}
+
+/* -- index page ------------------------------------------------------------ */
+
+table.contentstable {
+ width: 90%;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table.contentstable p.biglink {
+ line-height: 150%;
+}
+
+a.biglink {
+ font-size: 1.3em;
+}
+
+span.linkdescr {
+ font-style: italic;
+ padding-top: 5px;
+ font-size: 90%;
+}
+
+/* -- general index --------------------------------------------------------- */
+
+table.indextable {
+ width: 100%;
+}
+
+table.indextable td {
+ text-align: left;
+ vertical-align: top;
+}
+
+table.indextable ul {
+ margin-top: 0;
+ margin-bottom: 0;
+ list-style-type: none;
+}
+
+table.indextable > tbody > tr > td > ul {
+ padding-left: 0em;
+}
+
+table.indextable tr.pcap {
+ height: 10px;
+}
+
+table.indextable tr.cap {
+ margin-top: 10px;
+ background-color: #f2f2f2;
+}
+
+img.toggler {
+ margin-right: 3px;
+ margin-top: 3px;
+ cursor: pointer;
+}
+
+div.modindex-jumpbox {
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+ margin: 1em 0 1em 0;
+ padding: 0.4em;
+}
+
+div.genindex-jumpbox {
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+ margin: 1em 0 1em 0;
+ padding: 0.4em;
+}
+
+/* -- domain module index --------------------------------------------------- */
+
+table.modindextable td {
+ padding: 2px;
+ border-collapse: collapse;
+}
+
+/* -- general body styles --------------------------------------------------- */
+
+div.body {
+ min-width: 450px;
+ max-width: 800px;
+}
+
+div.body p, div.body dd, div.body li, div.body blockquote {
+ -moz-hyphens: auto;
+ -ms-hyphens: auto;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+}
+
+a.headerlink {
+ visibility: hidden;
+}
+
+a.brackets:before,
+span.brackets > a:before{
+ content: "[";
+}
+
+a.brackets:after,
+span.brackets > a:after {
+ content: "]";
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink,
+caption:hover > a.headerlink,
+p.caption:hover > a.headerlink,
+div.code-block-caption:hover > a.headerlink {
+ visibility: visible;
+}
+
+div.body p.caption {
+ text-align: inherit;
+}
+
+div.body td {
+ text-align: left;
+}
+
+.first {
+ margin-top: 0 !important;
+}
+
+p.rubric {
+ margin-top: 30px;
+ font-weight: bold;
+}
+
+img.align-left, figure.align-left, .figure.align-left, object.align-left {
+ clear: left;
+ float: left;
+ margin-right: 1em;
+}
+
+img.align-right, figure.align-right, .figure.align-right, object.align-right {
+ clear: right;
+ float: right;
+ margin-left: 1em;
+}
+
+img.align-center, figure.align-center, .figure.align-center, object.align-center {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+img.align-default, figure.align-default, .figure.align-default {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.align-left {
+ text-align: left;
+}
+
+.align-center {
+ text-align: center;
+}
+
+.align-default {
+ text-align: center;
+}
+
+.align-right {
+ text-align: right;
+}
+
+/* -- sidebars -------------------------------------------------------------- */
+
+div.sidebar,
+aside.sidebar {
+ margin: 0 0 0.5em 1em;
+ border: 1px solid #ddb;
+ padding: 7px;
+ background-color: #ffe;
+ width: 40%;
+ float: right;
+ clear: right;
+ overflow-x: auto;
+}
+
+p.sidebar-title {
+ font-weight: bold;
+}
+
+div.admonition, div.topic, blockquote {
+ clear: left;
+}
+
+/* -- topics ---------------------------------------------------------------- */
+
+div.topic {
+ border: 1px solid #ccc;
+ padding: 7px;
+ margin: 10px 0 10px 0;
+}
+
+p.topic-title {
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 10px;
+}
+
+/* -- admonitions ----------------------------------------------------------- */
+
+div.admonition {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 7px;
+}
+
+div.admonition dt {
+ font-weight: bold;
+}
+
+p.admonition-title {
+ margin: 0px 10px 5px 0px;
+ font-weight: bold;
+}
+
+div.body p.centered {
+ text-align: center;
+ margin-top: 25px;
+}
+
+/* -- content of sidebars/topics/admonitions -------------------------------- */
+
+div.sidebar > :last-child,
+aside.sidebar > :last-child,
+div.topic > :last-child,
+div.admonition > :last-child {
+ margin-bottom: 0;
+}
+
+div.sidebar::after,
+aside.sidebar::after,
+div.topic::after,
+div.admonition::after,
+blockquote::after {
+ display: block;
+ content: '';
+ clear: both;
+}
+
+/* -- tables ---------------------------------------------------------------- */
+
+table.docutils {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ border: 0;
+ border-collapse: collapse;
+}
+
+table.align-center {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table.align-default {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table caption span.caption-number {
+ font-style: italic;
+}
+
+table caption span.caption-text {
+}
+
+table.docutils td, table.docutils th {
+ padding: 1px 8px 1px 5px;
+ border-top: 0;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 1px solid #aaa;
+}
+
+table.footnote td, table.footnote th {
+ border: 0 !important;
+}
+
+th {
+ text-align: left;
+ padding-right: 5px;
+}
+
+table.citation {
+ border-left: solid 1px gray;
+ margin-left: 1px;
+}
+
+table.citation td {
+ border-bottom: none;
+}
+
+th > :first-child,
+td > :first-child {
+ margin-top: 0px;
+}
+
+th > :last-child,
+td > :last-child {
+ margin-bottom: 0px;
+}
+
+/* -- figures --------------------------------------------------------------- */
+
+div.figure, figure {
+ margin: 0.5em;
+ padding: 0.5em;
+}
+
+div.figure p.caption, figcaption {
+ padding: 0.3em;
+}
+
+div.figure p.caption span.caption-number,
+figcaption span.caption-number {
+ font-style: italic;
+}
+
+div.figure p.caption span.caption-text,
+figcaption span.caption-text {
+}
+
+/* -- field list styles ----------------------------------------------------- */
+
+table.field-list td, table.field-list th {
+ border: 0 !important;
+}
+
+.field-list ul {
+ margin: 0;
+ padding-left: 1em;
+}
+
+.field-list p {
+ margin: 0;
+}
+
+.field-name {
+ -moz-hyphens: manual;
+ -ms-hyphens: manual;
+ -webkit-hyphens: manual;
+ hyphens: manual;
+}
+
+/* -- hlist styles ---------------------------------------------------------- */
+
+table.hlist {
+ margin: 1em 0;
+}
+
+table.hlist td {
+ vertical-align: top;
+}
+
+/* -- object description styles --------------------------------------------- */
+
+.sig {
+ font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+}
+
+.sig-name, code.descname {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+.sig-name {
+ font-size: 1.1em;
+}
+
+code.descname {
+ font-size: 1.2em;
+}
+
+.sig-prename, code.descclassname {
+ background-color: transparent;
+}
+
+.optional {
+ font-size: 1.3em;
+}
+
+.sig-paren {
+ font-size: larger;
+}
+
+.sig-param.n {
+ font-style: italic;
+}
+
+/* C++ specific styling */
+
+.sig-inline.c-texpr,
+.sig-inline.cpp-texpr {
+ font-family: unset;
+}
+
+.sig.c .k, .sig.c .kt,
+.sig.cpp .k, .sig.cpp .kt {
+ color: #0033B3;
+}
+
+.sig.c .m,
+.sig.cpp .m {
+ color: #1750EB;
+}
+
+.sig.c .s, .sig.c .sc,
+.sig.cpp .s, .sig.cpp .sc {
+ color: #067D17;
+}
+
+
+/* -- other body styles ----------------------------------------------------- */
+
+ol.arabic {
+ list-style: decimal;
+}
+
+ol.loweralpha {
+ list-style: lower-alpha;
+}
+
+ol.upperalpha {
+ list-style: upper-alpha;
+}
+
+ol.lowerroman {
+ list-style: lower-roman;
+}
+
+ol.upperroman {
+ list-style: upper-roman;
+}
+
+:not(li) > ol > li:first-child > :first-child,
+:not(li) > ul > li:first-child > :first-child {
+ margin-top: 0px;
+}
+
+:not(li) > ol > li:last-child > :last-child,
+:not(li) > ul > li:last-child > :last-child {
+ margin-bottom: 0px;
+}
+
+ol.simple ol p,
+ol.simple ul p,
+ul.simple ol p,
+ul.simple ul p {
+ margin-top: 0;
+}
+
+ol.simple > li:not(:first-child) > p,
+ul.simple > li:not(:first-child) > p {
+ margin-top: 0;
+}
+
+ol.simple p,
+ul.simple p {
+ margin-bottom: 0;
+}
+
+dl.footnote > dt,
+dl.citation > dt {
+ float: left;
+ margin-right: 0.5em;
+}
+
+dl.footnote > dd,
+dl.citation > dd {
+ margin-bottom: 0em;
+}
+
+dl.footnote > dd:after,
+dl.citation > dd:after {
+ content: "";
+ clear: both;
+}
+
+dl.field-list {
+ display: grid;
+ grid-template-columns: fit-content(30%) auto;
+}
+
+dl.field-list > dt {
+ font-weight: bold;
+ word-break: break-word;
+ padding-left: 0.5em;
+ padding-right: 5px;
+}
+
+dl.field-list > dt:after {
+ content: ":";
+}
+
+dl.field-list > dd {
+ padding-left: 0.5em;
+ margin-top: 0em;
+ margin-left: 0em;
+ margin-bottom: 0em;
+}
+
+dl {
+ margin-bottom: 15px;
+}
+
+dd > :first-child {
+ margin-top: 0px;
+}
+
+dd ul, dd table {
+ margin-bottom: 10px;
+}
+
+dd {
+ margin-top: 3px;
+ margin-bottom: 10px;
+ margin-left: 30px;
+}
+
+dl > dd:last-child,
+dl > dd:last-child > :last-child {
+ margin-bottom: 0;
+}
+
+dt:target, span.highlighted {
+ background-color: #fbe54e;
+}
+
+rect.highlighted {
+ fill: #fbe54e;
+}
+
+dl.glossary dt {
+ font-weight: bold;
+ font-size: 1.1em;
+}
+
+.versionmodified {
+ font-style: italic;
+}
+
+.system-message {
+ background-color: #fda;
+ padding: 5px;
+ border: 3px solid red;
+}
+
+.footnote:target {
+ background-color: #ffa;
+}
+
+.line-block {
+ display: block;
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+
+.line-block .line-block {
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 1.5em;
+}
+
+.guilabel, .menuselection {
+ font-family: sans-serif;
+}
+
+.accelerator {
+ text-decoration: underline;
+}
+
+.classifier {
+ font-style: oblique;
+}
+
+.classifier:before {
+ font-style: normal;
+ margin: 0 0.5em;
+ content: ":";
+ display: inline-block;
+}
+
+abbr, acronym {
+ border-bottom: dotted 1px;
+ cursor: help;
+}
+
+/* -- code displays --------------------------------------------------------- */
+
+pre {
+ overflow: auto;
+ overflow-y: hidden; /* fixes display issues on Chrome browsers */
+}
+
+pre, div[class*="highlight-"] {
+ clear: both;
+}
+
+span.pre {
+ -moz-hyphens: none;
+ -ms-hyphens: none;
+ -webkit-hyphens: none;
+ hyphens: none;
+ white-space: nowrap;
+}
+
+div[class*="highlight-"] {
+ margin: 1em 0;
+}
+
+td.linenos pre {
+ border: 0;
+ background-color: transparent;
+ color: #aaa;
+}
+
+table.highlighttable {
+ display: block;
+}
+
+table.highlighttable tbody {
+ display: block;
+}
+
+table.highlighttable tr {
+ display: flex;
+}
+
+table.highlighttable td {
+ margin: 0;
+ padding: 0;
+}
+
+table.highlighttable td.linenos {
+ padding-right: 0.5em;
+}
+
+table.highlighttable td.code {
+ flex: 1;
+ overflow: hidden;
+}
+
+.highlight .hll {
+ display: block;
+}
+
+div.highlight pre,
+table.highlighttable pre {
+ margin: 0;
+}
+
+div.code-block-caption + div {
+ margin-top: 0;
+}
+
+div.code-block-caption {
+ margin-top: 1em;
+ padding: 2px 5px;
+ font-size: small;
+}
+
+div.code-block-caption code {
+ background-color: transparent;
+}
+
+table.highlighttable td.linenos,
+span.linenos,
+div.highlight span.gp { /* gp: Generic.Prompt */
+ user-select: none;
+ -webkit-user-select: text; /* Safari fallback only */
+ -webkit-user-select: none; /* Chrome/Safari */
+ -moz-user-select: none; /* Firefox */
+ -ms-user-select: none; /* IE10+ */
+}
+
+div.code-block-caption span.caption-number {
+ padding: 0.1em 0.3em;
+ font-style: italic;
+}
+
+div.code-block-caption span.caption-text {
+}
+
+div.literal-block-wrapper {
+ margin: 1em 0;
+}
+
+code.xref, a code {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
+ background-color: transparent;
+}
+
+.viewcode-link {
+ float: right;
+}
+
+.viewcode-back {
+ float: right;
+ font-family: sans-serif;
+}
+
+div.viewcode-block:target {
+ margin: -1px -10px;
+ padding: 0 10px;
+}
+
+/* -- math display ---------------------------------------------------------- */
+
+img.math {
+ vertical-align: middle;
+}
+
+div.body div.math p {
+ text-align: center;
+}
+
+span.eqno {
+ float: right;
+}
+
+span.eqno a.headerlink {
+ position: absolute;
+ z-index: 1;
+}
+
+div.math:hover a.headerlink {
+ visibility: visible;
+}
+
+/* -- printout stylesheet --------------------------------------------------- */
+
+@media print {
+ div.document,
+ div.documentwrapper,
+ div.bodywrapper {
+ margin: 0 !important;
+ width: 100%;
+ }
+
+ div.sphinxsidebar,
+ div.related,
+ div.footer,
+ #top-link {
+ display: none;
+ }
+}
\ No newline at end of file
diff --git a/docs/_build/html/_static/custom.css b/docs/_build/html/_static/custom.css
new file mode 100644
index 0000000..2a924f1
--- /dev/null
+++ b/docs/_build/html/_static/custom.css
@@ -0,0 +1 @@
+/* This file intentionally left blank. */
diff --git a/docs/_build/html/_static/doctools.js b/docs/_build/html/_static/doctools.js
new file mode 100644
index 0000000..e509e48
--- /dev/null
+++ b/docs/_build/html/_static/doctools.js
@@ -0,0 +1,326 @@
+/*
+ * doctools.js
+ * ~~~~~~~~~~~
+ *
+ * Sphinx JavaScript utilities for all documentation.
+ *
+ * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/**
+ * select a different prefix for underscore
+ */
+$u = _.noConflict();
+
+/**
+ * make the code below compatible with browsers without
+ * an installed firebug like debugger
+if (!window.console || !console.firebug) {
+ var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
+ "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
+ "profile", "profileEnd"];
+ window.console = {};
+ for (var i = 0; i < names.length; ++i)
+ window.console[names[i]] = function() {};
+}
+ */
+
+/**
+ * small helper function to urldecode strings
+ *
+ * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
+ */
+jQuery.urldecode = function(x) {
+ if (!x) {
+ return x
+ }
+ return decodeURIComponent(x.replace(/\+/g, ' '));
+};
+
+/**
+ * small helper function to urlencode strings
+ */
+jQuery.urlencode = encodeURIComponent;
+
+/**
+ * This function returns the parsed url parameters of the
+ * current request. Multiple values per key are supported,
+ * it will always return arrays of strings for the value parts.
+ */
+jQuery.getQueryParameters = function(s) {
+ if (typeof s === 'undefined')
+ s = document.location.search;
+ var parts = s.substr(s.indexOf('?') + 1).split('&');
+ var result = {};
+ for (var i = 0; i < parts.length; i++) {
+ var tmp = parts[i].split('=', 2);
+ var key = jQuery.urldecode(tmp[0]);
+ var value = jQuery.urldecode(tmp[1]);
+ if (key in result)
+ result[key].push(value);
+ else
+ result[key] = [value];
+ }
+ return result;
+};
+
+/**
+ * highlight a given string on a jquery object by wrapping it in
+ * span elements with the given class name.
+ */
+jQuery.fn.highlightText = function(text, className) {
+ function highlight(node, addItems) {
+ if (node.nodeType === 3) {
+ var val = node.nodeValue;
+ var pos = val.toLowerCase().indexOf(text);
+ if (pos >= 0 &&
+ !jQuery(node.parentNode).hasClass(className) &&
+ !jQuery(node.parentNode).hasClass("nohighlight")) {
+ var span;
+ var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
+ if (isInSVG) {
+ span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
+ } else {
+ span = document.createElement("span");
+ span.className = className;
+ }
+ span.appendChild(document.createTextNode(val.substr(pos, text.length)));
+ node.parentNode.insertBefore(span, node.parentNode.insertBefore(
+ document.createTextNode(val.substr(pos + text.length)),
+ node.nextSibling));
+ node.nodeValue = val.substr(0, pos);
+ if (isInSVG) {
+ var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
+ var bbox = node.parentElement.getBBox();
+ rect.x.baseVal.value = bbox.x;
+ rect.y.baseVal.value = bbox.y;
+ rect.width.baseVal.value = bbox.width;
+ rect.height.baseVal.value = bbox.height;
+ rect.setAttribute('class', className);
+ addItems.push({
+ "parent": node.parentNode,
+ "target": rect});
+ }
+ }
+ }
+ else if (!jQuery(node).is("button, select, textarea")) {
+ jQuery.each(node.childNodes, function() {
+ highlight(this, addItems);
+ });
+ }
+ }
+ var addItems = [];
+ var result = this.each(function() {
+ highlight(this, addItems);
+ });
+ for (var i = 0; i < addItems.length; ++i) {
+ jQuery(addItems[i].parent).before(addItems[i].target);
+ }
+ return result;
+};
+
+/*
+ * backward compatibility for jQuery.browser
+ * This will be supported until firefox bug is fixed.
+ */
+if (!jQuery.browser) {
+ jQuery.uaMatch = function(ua) {
+ ua = ua.toLowerCase();
+
+ var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
+ /(webkit)[ \/]([\w.]+)/.exec(ua) ||
+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
+ /(msie) ([\w.]+)/.exec(ua) ||
+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
+ [];
+
+ return {
+ browser: match[ 1 ] || "",
+ version: match[ 2 ] || "0"
+ };
+ };
+ jQuery.browser = {};
+ jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
+}
+
+/**
+ * Small JavaScript module for the documentation.
+ */
+var Documentation = {
+
+ init : function() {
+ this.fixFirefoxAnchorBug();
+ this.highlightSearchWords();
+ this.initIndexTable();
+ if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
+ this.initOnKeyListeners();
+ }
+ },
+
+ /**
+ * i18n support
+ */
+ TRANSLATIONS : {},
+ PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
+ LOCALE : 'unknown',
+
+ // gettext and ngettext don't access this so that the functions
+ // can safely bound to a different name (_ = Documentation.gettext)
+ gettext : function(string) {
+ var translated = Documentation.TRANSLATIONS[string];
+ if (typeof translated === 'undefined')
+ return string;
+ return (typeof translated === 'string') ? translated : translated[0];
+ },
+
+ ngettext : function(singular, plural, n) {
+ var translated = Documentation.TRANSLATIONS[singular];
+ if (typeof translated === 'undefined')
+ return (n == 1) ? singular : plural;
+ return translated[Documentation.PLURALEXPR(n)];
+ },
+
+ addTranslations : function(catalog) {
+ for (var key in catalog.messages)
+ this.TRANSLATIONS[key] = catalog.messages[key];
+ this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
+ this.LOCALE = catalog.locale;
+ },
+
+ /**
+ * add context elements like header anchor links
+ */
+ addContextElements : function() {
+ $('div[id] > :header:first').each(function() {
+ $('\u00B6').
+ attr('href', '#' + this.id).
+ attr('title', _('Permalink to this headline')).
+ appendTo(this);
+ });
+ $('dt[id]').each(function() {
+ $('\u00B6').
+ attr('href', '#' + this.id).
+ attr('title', _('Permalink to this definition')).
+ appendTo(this);
+ });
+ },
+
+ /**
+ * workaround a firefox stupidity
+ * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
+ */
+ fixFirefoxAnchorBug : function() {
+ if (document.location.hash && $.browser.mozilla)
+ window.setTimeout(function() {
+ document.location.href += '';
+ }, 10);
+ },
+
+ /**
+ * highlight the search words provided in the url in the text
+ */
+ highlightSearchWords : function() {
+ var params = $.getQueryParameters();
+ var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
+ if (terms.length) {
+ var body = $('div.body');
+ if (!body.length) {
+ body = $('body');
+ }
+ window.setTimeout(function() {
+ $.each(terms, function() {
+ body.highlightText(this.toLowerCase(), 'highlighted');
+ });
+ }, 10);
+ $('