extinclude attempt
This commit is contained in:
parent
2d02da9939
commit
9199631ea5
9 changed files with 201 additions and 918 deletions
49
docs/conf.py
49
docs/conf.py
|
@ -10,12 +10,14 @@
|
|||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
|
||||
import sys, os
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
#sys.path.append(os.path.abspath('ext'))
|
||||
sys.path.append('.')
|
||||
|
||||
# shows/hides the todos
|
||||
todo_include_todos = True
|
||||
todo_include_todos = False
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
|
@ -40,32 +42,29 @@ release = '1.0'
|
|||
# ones.
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.extlinks', 'sphinx_lesson', 'sphinx.ext.todo'
|
||||
#'myst_parser', 'sphinx.ext.extlinks'
|
||||
'sphinx.ext.extlinks', 'sphinx_lesson', 'sphinx.ext.todo',
|
||||
'sphinx.ext.extlinks', 'ext.xref', 'ext.extinclude'
|
||||
]
|
||||
#
|
||||
#myst_enable_extensions = [
|
||||
# "amsmath",
|
||||
# "attrs_inline",
|
||||
# "colon_fence",
|
||||
# "deflist",
|
||||
# "dollarmath",
|
||||
# "fieldlist",
|
||||
# "html_admonition",
|
||||
# "html_image",
|
||||
## "linkify",
|
||||
# "replacements",
|
||||
# "smartquotes",
|
||||
# "strikethrough",
|
||||
# "substitution",
|
||||
# "tasklist",
|
||||
#]
|
||||
|
||||
#uses the xref.py extension
|
||||
xref_links = {"link_name" : ("user text", "url")}
|
||||
|
||||
link_name = "Sphinx External Links"
|
||||
user_text = "modified External Links Extension"
|
||||
url = "http://www.sphinx-doc.org/en/stable/ext/extlinks.html"
|
||||
|
||||
links = {
|
||||
'tiramisu': ('Tiramisu', 'https://tiramisu.readthedocs.io/en/latest/'),
|
||||
'tiramisu library': ('Tiramisu library homepage', 'https://forge.cloud.silique.fr/stove/tiramisu'),
|
||||
}
|
||||
|
||||
xref_links.update(links)
|
||||
|
||||
# **extlinks** 'sphinx.ext.extlinks',
|
||||
# enables syntax like :proxy:`my source <hello>` in the src files
|
||||
extlinks = {'proxy': ('/proxy/%s.html',
|
||||
'external link: ')}
|
||||
|
||||
extlinks = {'source': ('https://forge.cloud.silique.fr/stove/rougail-tutorials/src/commit/%s',
|
||||
'source: %s')}
|
||||
|
||||
default_role = "code"
|
||||
|
||||
|
@ -111,7 +110,7 @@ language = 'en'
|
|||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
exclude_patterns = ['.venv', 'build', '_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = None
|
||||
|
|
32
docs/ext/extinclude.py
Normal file
32
docs/ext/extinclude.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
from __future__ import annotations
|
||||
|
||||
|
||||
from docutils import nodes
|
||||
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
|
||||
from sphinx.util.docutils import SphinxDirective, SphinxRole
|
||||
|
||||
from sphinx.util.typing import ExtensionMetadata
|
||||
|
||||
class HelloDirective(SphinxDirective):
|
||||
"""A directive to say hello!"""
|
||||
|
||||
required_arguments = 1
|
||||
|
||||
|
||||
def run(self) -> list[nodes.Node]:
|
||||
paragraph_node = nodes.paragraph(text=f'hello {self.arguments[0]}!')
|
||||
return [paragraph_node]
|
||||
|
||||
|
||||
def setup(app: Sphinx) -> ExtensionMetadata:
|
||||
|
||||
app.add_directive('hello', HelloDirective)
|
||||
|
||||
return {
|
||||
'version': '0.1',
|
||||
'parallel_read_safe': True,
|
||||
'parallel_write_safe': True,
|
||||
}
|
42
docs/ext/xref.py
Normal file
42
docs/ext/xref.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
"""adds link url in the global scope
|
||||
"""
|
||||
from docutils import nodes
|
||||
|
||||
from sphinx.util import caption_ref_re
|
||||
|
||||
def xref( typ, rawtext, text, lineno, inliner, options={}, content=[] ):
|
||||
|
||||
title = target = text
|
||||
titleistarget = True
|
||||
# look if explicit title and target are given with `foo <bar>` syntax
|
||||
brace = text.find('<')
|
||||
if brace != -1:
|
||||
titleistarget = False
|
||||
m = caption_ref_re.match(text)
|
||||
if m:
|
||||
target = m.group(2)
|
||||
title = m.group(1)
|
||||
else:
|
||||
# fallback: everything after '<' is the target
|
||||
target = text[brace+1:]
|
||||
title = text[:brace]
|
||||
|
||||
link = xref.links[target]
|
||||
|
||||
if brace != -1:
|
||||
pnode = nodes.reference(target, title, refuri=link[1])
|
||||
else:
|
||||
pnode = nodes.reference(target, link[0], refuri=link[1])
|
||||
|
||||
return [pnode], []
|
||||
|
||||
def get_refs(app):
|
||||
|
||||
xref.links = app.config.xref_links
|
||||
|
||||
def setup(app):
|
||||
|
||||
app.add_config_value('xref_links', {}, True)
|
||||
app.add_role('xref', xref)
|
||||
app.connect("builder-inited", get_refs)
|
||||
|
110
docs/fill.rst
110
docs/fill.rst
|
@ -23,64 +23,64 @@ Parameters
|
|||
|
||||
Depending on the types of calculation, the parameters will be different:
|
||||
|
||||
.. list-table::
|
||||
.. list-table::
|
||||
:widths: 15 25 20 15
|
||||
:header-rows: 1
|
||||
|
||||
* - Calculation type
|
||||
|
||||
* - Calculation type
|
||||
- Parameter
|
||||
- Comments
|
||||
- Sample
|
||||
|
||||
* -
|
||||
- **type**
|
||||
|
||||
* -
|
||||
- **type**
|
||||
|
||||
`string`
|
||||
|
||||
|
||||
`mandatory`
|
||||
|
||||
|
||||
- Type of calculation, possible values are: jinja, variable, information, suffix or index
|
||||
- jinja
|
||||
* - Jinja
|
||||
* - Jinja
|
||||
- **jinja**
|
||||
|
||||
|
||||
`string`
|
||||
|
||||
|
||||
`mandatory`
|
||||
- Template Jinja. For a multiple variable, each line represents a value.
|
||||
- `{% if rougail.variable %}
|
||||
- `{% if rougail.variable %}`
|
||||
|
||||
{{ rougail.variable }}
|
||||
`{{ rougail.variable }}`
|
||||
|
||||
{% endif %}`
|
||||
* - Jinja
|
||||
- **params**
|
||||
|
||||
`list`
|
||||
`{% endif %}`
|
||||
* - Jinja
|
||||
- **params**
|
||||
|
||||
`list`
|
||||
- Additional parameters passed to the Jinja template
|
||||
-
|
||||
-
|
||||
* - Variable (`mandatory`)
|
||||
|
||||
Information
|
||||
- **variable**
|
||||
- **variable**
|
||||
|
||||
`string`
|
||||
- Name of associated variable
|
||||
- rougail.variable
|
||||
- rougail.variable
|
||||
* - Variable
|
||||
- **propertyerror**
|
||||
|
||||
- **propertyerror**
|
||||
|
||||
`boolean`
|
||||
- If access to the variable is not possible due to a property (for example `disabled`) by default an error is returned. If the attribute is `false`, the calculated value is empty.
|
||||
|
||||
**Default value:** `true`
|
||||
- false
|
||||
|
||||
- false
|
||||
|
||||
* - Information
|
||||
- **information**
|
||||
|
||||
|
||||
`string`
|
||||
|
||||
|
||||
`mandatory`
|
||||
- Name of the information whose value we want to retrieve.
|
||||
- doc
|
||||
|
@ -98,60 +98,60 @@ There are two types of parameter:
|
|||
- parameter via a suffix: in the case of a variable in a dynamic family
|
||||
- parameter via an index: in the case of a follower variable
|
||||
|
||||
.. list-table::
|
||||
.. list-table::
|
||||
:widths: 15 25 20 15
|
||||
:header-rows: 1
|
||||
|
||||
* - Parameter type
|
||||
|
||||
* - Parameter type
|
||||
- Parameter
|
||||
- Comments
|
||||
- Sample
|
||||
|
||||
* -
|
||||
* -
|
||||
- **name**
|
||||
|
||||
|
||||
`string`
|
||||
|
||||
|
||||
`mandatory`
|
||||
- parameter's name
|
||||
- my_param
|
||||
* -
|
||||
- my_param
|
||||
* -
|
||||
- **type**
|
||||
|
||||
|
||||
`string`
|
||||
|
||||
|
||||
`mandatory`
|
||||
- parameter's type, possible values are: variable, information, suffix or index
|
||||
- suffix
|
||||
* - Variable
|
||||
- **variable**
|
||||
|
||||
|
||||
`string`
|
||||
|
||||
|
||||
`mandatory`
|
||||
|
||||
- Variable's name
|
||||
|
||||
- Variable's name
|
||||
- rougail.variable
|
||||
* - Variable (`mandatory`) information
|
||||
- **propertyerror**
|
||||
|
||||
- **propertyerror**
|
||||
|
||||
`boolean`
|
||||
- If access to the variable is not possible due to a property (for example `disabled`) by default an error is returned. If the attribute is `False`, the parameter is not passed to the Jinja template.
|
||||
- **Default value**: `True`
|
||||
* - Variable
|
||||
* - Variable
|
||||
- **optional**
|
||||
|
||||
|
||||
`boolean`
|
||||
- The variable may not exist depending on YAML file imports.
|
||||
- The variable may not exist depending on YAML file imports.
|
||||
If the optional parameter is `True`, the parameter will simply be deleted if the variable does not exist.
|
||||
|
||||
Default value : `False`
|
||||
Default value : `False`
|
||||
- True
|
||||
* - Information
|
||||
- **information**
|
||||
|
||||
|
||||
`string`
|
||||
|
||||
|
||||
`mandatory`
|
||||
- Name of the information whose value we want to retrieve.
|
||||
- doc
|
||||
|
@ -170,6 +170,7 @@ Inside those namespaces we can add families and variables.
|
|||
Here is an hierarchic examples:
|
||||
|
||||
.. code-block::
|
||||
|
||||
rougail
|
||||
├── variable1
|
||||
├── family1
|
||||
|
@ -210,6 +211,7 @@ Dynamic family
|
|||
Hire is a dynamic family "{{ suffix }}":
|
||||
|
||||
.. code-block::
|
||||
|
||||
rougail
|
||||
├── variable1: ["val1", "val2"]
|
||||
├── {{ suffix }}
|
||||
|
@ -254,7 +256,7 @@ Let's start with an example from a simple Jinja template:
|
|||
type: jinja
|
||||
jinja: 'no'
|
||||
|
||||
Here is a second example with a boolean variable:
|
||||
Here is a second example with a boolean variable:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
|
@ -280,7 +282,7 @@ And a multiple value of the number type:
|
|||
jinja: |
|
||||
1
|
||||
2
|
||||
3
|
||||
3
|
||||
|
||||
Let's create a variable whose value is returned by a python function:
|
||||
|
||||
|
@ -295,7 +297,7 @@ Let's create a variable whose value is returned by a python function:
|
|||
|
||||
Then let's create the `return_no` function:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
def return_no():
|
||||
return 'no'
|
||||
|
@ -377,7 +379,7 @@ An example with an index type parameter:
|
|||
Calculation via a variable
|
||||
-----------------------------
|
||||
|
||||
Copy a variable in another:
|
||||
Copy a variable in another:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
|
@ -481,7 +483,7 @@ Second example using the variable for all suffixes:
|
|||
.. code-block:: yaml
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
version: '1.1'
|
||||
varname:
|
||||
multi: true
|
||||
default:
|
||||
|
|
|
@ -1,27 +1,34 @@
|
|||
.. |Tiramisu| replace:: Tiramisu
|
||||
.. _tiramisu: https://forge.cloud.silique.fr/stove/tiramisu
|
||||
|
||||
Getting started
|
||||
====================
|
||||
|
||||
What is a consistency handling system ?
|
||||
------------------------------------------------
|
||||
|
||||
.. questions:: Question: "OK, I have understood that the Rougail stuff enables me to take advantage of |Tiramisu|. But what is all this for? What is exactly a consistency handling system? And again, what is this |Tiramisu| library used for?"
|
||||
.. questions::
|
||||
|
||||
*Answer*: Well, let's explain what |Tiramisu| is and how we are using the |Tiramisu| library.
|
||||
"OK, I have understood that the Rougail stuff enables me to take advantage of :xref:`tiramisu`.
|
||||
|
||||
But what is all this for?
|
||||
|
||||
What is exactly a consistency handling system?
|
||||
|
||||
And again, what is this :xref:`tiramisu` library used for?"
|
||||
|
||||
*Answer*: Well, now we explain what this :xref:`tiramisu` library is, and how we are using it.
|
||||
|
||||
.. glossary::
|
||||
|
||||
Tiramisu
|
||||
|
||||
|Tiramisu| is a consistency handling system that has initially been designed
|
||||
:xref:`tiramisu` is a consistency handling system that has initially been designed
|
||||
in the configuration management scope. To put it more simply,
|
||||
this library is generally used to handle configuration options.
|
||||
|
||||
It manages variables and group of variables. In the Tiramisu scope we call
|
||||
it *options* and *option descriptions*.
|
||||
|
||||
Here is the :xref:`tiramisu library`.
|
||||
|
||||
In the Rougail scope, we call it :term:`variable`\ s and :term:`families`.
|
||||
In Rougail, the families and variables are located in the :term:`dictionaries`.
|
||||
|
||||
|
@ -57,7 +64,22 @@ The YAML dictionaries format
|
|||
|
||||
Before getting started with Rougail we need to learn the specifics of the YAML dictionaries file format (as well as some templating concepts).
|
||||
|
||||
.. FIXME parler de jinja https://jinja.palletsprojects.com
|
||||
.. todo:: parler de jinja https://jinja.palletsprojects.com
|
||||
|
||||
|
||||
.. _empty_dictionary:
|
||||
|
||||
Here is an empty rougail dictionary YAML file
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
---
|
||||
version: 1.1
|
||||
|
||||
:source:`v1.1_001/firefox/00-proxy.yml`
|
||||
|
||||
|
||||
.. hello:: world
|
||||
|
||||
Here is a :term:`dictionary` example:
|
||||
|
||||
|
@ -189,3 +211,4 @@ We then have the output:
|
|||
.. code-block:: python
|
||||
|
||||
{'rougail.world.name': 'rougail'}
|
||||
|
||||
|
|
|
@ -170,6 +170,7 @@ Here an example to a lipogram option (in a string, we cannot use "e" character):
|
|||
To add the new lipogram type in Rougail:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> from rougail import Rougail, RougailConfig
|
||||
>>> RougailConfig['dictionaries_dir'] = ['dict']
|
||||
>>> RougailConfig['custom_types']['lipogram'] = LipogramOption
|
||||
|
@ -178,12 +179,14 @@ Now, we can use lipogram type.
|
|||
Here is a :file:`dict/00-base.yml` dictionary:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
var:
|
||||
type: lipogram
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> rougail = Rougail()
|
||||
>>> config = rougail.get_config()
|
||||
>>> config.option('rougail.var').value.set('blah')
|
||||
|
@ -212,6 +215,7 @@ We create a term:`dictionary` named :file:`dict/01-upgrade.yml` with version 1.0
|
|||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> from rougail import RougailUpgrade, RougailConfig
|
||||
>>> RougailConfig['dictionaries_dir'] = ['dict']
|
||||
>>> upgrade = RougailUpgrade()
|
||||
|
|
|
@ -1,832 +0,0 @@
|
|||
Tutorial: a real world sample
|
||||
==============================
|
||||
|
||||
.. demo:: Demonstration : configuring (the setting of) your favorite web browser
|
||||
|
||||
This tutorial shows to you an example of Rougail use on
|
||||
how to set a proxy in the `Mozilla Firefox <https://www.mozilla.org/en-US/firefox/new/>`_ browser.
|
||||
|
||||
More precisely, this tutorial aims at reproducing this Mozilla Firefox settings page:
|
||||
|
||||
.. image:: images/firefox.png
|
||||
|
||||
.. important:: Here we are in the configuration validation use case,
|
||||
that is the values entered by the user have to be validated.
|
||||
It's a common use case, but not the only one.
|
||||
|
||||
Let's explain this use case.
|
||||
|
||||
The Firefox proxy configuration
|
||||
-------------------------------------------
|
||||
|
||||
The `proxy` family
|
||||
-------------------
|
||||
|
||||
Let's create our first :term:`dictionary`.
|
||||
|
||||
.. prerequisites:: Let's create a folder named `dict` and a dictionary file inside
|
||||
|
||||
We will put our dictionary files in this folder.
|
||||
|
||||
Then let's put our first dictionary file in this folder, named :file:`00-proxy.yml`
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: the :file:`00-proxy.yml` file
|
||||
:linenos:
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
proxy:
|
||||
description: Proxy configuration in order to have access to the internet
|
||||
type: family
|
||||
|
||||
We can see that we have defined a :term:`family` here, and this family is *empty*
|
||||
(that is, the family container contains no variable yet).
|
||||
|
||||
.. admonition:: If a family is empty
|
||||
|
||||
We need to specify the :term:`family` type (line 5) here because if we don't,
|
||||
the Rougail's type engine will infer it by default as a :term:`variable`.
|
||||
|
||||
It's because we don't have set any :term:`variable` inside.
|
||||
|
||||
|
||||
.. note:: The variables will be created in several files for educational purposes.
|
||||
Obviously all the variables can be put in the same file.
|
||||
|
||||
|
||||
The proxy's configuration type
|
||||
----------------------------------
|
||||
|
||||
In the Firefox configuration, it is possible to define several configuration modes,
|
||||
from no proxy at all (`no proxy`) to a kind of automatic configuration mode from a file (`set up proxy configuration from a file`).
|
||||
|
||||
We're gonna create a first variable in this family with "Proxy mode" as the description.
|
||||
Let's create a second :file:`dict/01-proxy_mode.yml` file.
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: the :file:`001-proxy_mode.yml` file
|
||||
:linenos:
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
proxy:
|
||||
proxy_mode:
|
||||
description: Proxy mode
|
||||
type: choice
|
||||
choices:
|
||||
- No proxy
|
||||
- Auto-detect proxy settings for this network
|
||||
- Use system proxy settings
|
||||
- Manual proxy configuration
|
||||
- Automatic proxy configuration URL
|
||||
default: No proxy
|
||||
|
||||
The `proxy_mode` variable requires a value (that is, `None` is not an option).
|
||||
It shall have a value, but what if the user *does not* specify any value?
|
||||
There is line 13, a possibility of setting a default value, wich is `No proxy` as the default.
|
||||
|
||||
The `proxy_mode` setting is "choice" (`type: choice`) means that
|
||||
there is a list of available values that can be selected.
|
||||
We say that the `proxy_mode` variable is *constrained* (by choices).
|
||||
|
||||
Line 8 to 12, we have the list of the possible (authorized) values:
|
||||
|
||||
- No proxy
|
||||
- Auto-detect proxy settings for this network
|
||||
- Use system proxy settings
|
||||
- Manual proxy configuration
|
||||
- Automatic proxy configuration URL
|
||||
|
||||
Now let's test our first two dictionaries:
|
||||
|
||||
|
||||
>>> from rougail import Rougail, RougailConfig
|
||||
>>> from pprint import pprint
|
||||
>>> RougailConfig['dictionaries_dir'] = ['dict']
|
||||
>>> rougail = Rougail()
|
||||
>>> config = rougail.get_config()
|
||||
>>> config.property.read_only()
|
||||
>>> pprint(config.value.get(), sort_dicts=False)
|
||||
{'rougail.proxy.proxy_mode': 'No proxy'}
|
||||
|
||||
The manual mode
|
||||
------------------
|
||||
|
||||
.. questions:: OK then. What happens when you select the "Manual proxy configuration"?
|
||||
|
||||
A good configuration design is to place all the proxy's manual configuration in a :term:`family`.
|
||||
Let's create the :file:`dict/02-proxy_manual.yml` dictionary:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: the the :file:`dict/02-proxy_manual.yml` file
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
proxy:
|
||||
manual:
|
||||
description: Manual proxy configuration
|
||||
type: family
|
||||
disabled:
|
||||
type: jinja
|
||||
jinja: |
|
||||
{% if rougail.proxy.proxy_mode != 'Manual proxy configuration' %}
|
||||
the proxy mode is not manual
|
||||
{% endif %}
|
||||
|
||||
Well, if the user selects the "Manual proxy configuration" proxy mode, we want to see a new subfamily (that is, a new set of configuration variables) called `manual` to appear (which is disabled).
|
||||
|
||||
.. glossary::
|
||||
|
||||
subfamily
|
||||
|
||||
A subfamily is just a family inside a family, a family that contains a family.
|
||||
|
||||
.. questions:: What about this `Jinja` type?
|
||||
|
||||
If the :term:`Jinja` template returns some text, then the family will be `disabled`. Otherwise it is accessible.
|
||||
Deactivating a family means that we will not be able to access it as well as the variables or families included in this family.
|
||||
|
||||
.. note:: If the Jinja template does not return any text, the variable will be **enabled**.
|
||||
Here we are using the Jinja condition statement.
|
||||
|
||||
.. glossary::
|
||||
|
||||
Jinja
|
||||
|
||||
`Jinja <https://jinja.palletsprojects.com>`_ is a template engine.
|
||||
we are using Jinja in a classical way, that is, Jinja allows us to handle different cases,
|
||||
for example with the `if` statement.
|
||||
|
||||
The HTTP proxy configuration
|
||||
------------------------------
|
||||
|
||||
In this family let's add a *subfamily* named `http_proxy`, containing the address and port configuration variables.
|
||||
|
||||
Let's create the :file:`dict/03-proxy_manual_http_proxy.yml` dictionary:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: the the :file:`dict/02-proxy_manual.yml` file
|
||||
:linenos:
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
proxy:
|
||||
manual:
|
||||
http_proxy:
|
||||
description: HTTP Proxy
|
||||
address:
|
||||
description: HTTP address
|
||||
type: domainname
|
||||
port:
|
||||
description: HTTP Port
|
||||
type: port
|
||||
default: '8080'
|
||||
|
||||
Both variables `address` and `port` have particular types (respectively `domainname` line 9 and `port` line 12) to validate the values configured by the user.
|
||||
|
||||
.. note:: No need to specify the type of the `http_proxy` as a family type, because here we have declared variables inside of it.
|
||||
|
||||
Duplicating the HTTP configuration to HTTPS
|
||||
---------------------------------------------
|
||||
|
||||
We then want to offer the user the possibility of providing the same proxy for the HTTPS requests. Let's create the :file:`dict/04-proxy_manual_http_use_for_https.yml` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: the :file:`dict/04-proxy_manual_http_use_for_https.yml` file
|
||||
|
||||
version: '1.1'
|
||||
proxy:
|
||||
manual:
|
||||
use_for_https:
|
||||
description: Also use this proxy for HTTPS
|
||||
type: boolean
|
||||
|
||||
This variable is a `boolean` type, its default value is `True`.
|
||||
|
||||
HTTPS proxy configuration detail
|
||||
-----------------------------------
|
||||
|
||||
Let's add a new subfamily named `ssl_proxy`, containing the `address` and `port` variables.
|
||||
|
||||
Let's create the :file:`dict/05-proxy_manual_ssl_proxy.yml` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: the :file:`dict/04-proxy_manual_http_use_for_https.yml` file
|
||||
:linenos:
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
proxy:
|
||||
manual:
|
||||
ssl_proxy:
|
||||
description: HTTPS Proxy
|
||||
hidden:
|
||||
type: variable
|
||||
variable: rougail.proxy.manual.use_for_https
|
||||
address:
|
||||
description: HTTPS address
|
||||
type: domainname
|
||||
default:
|
||||
type: jinja
|
||||
jinja: |
|
||||
{% if rougail.proxy.manual.use_for_https %}
|
||||
{{ rougail.proxy.manual.http_proxy.address }}
|
||||
{% endif %}
|
||||
port:
|
||||
description: HTTPS Port
|
||||
type: port
|
||||
default:
|
||||
type: jinja
|
||||
jinja: |
|
||||
{% if rougail.proxy.manual.use_for_https %}
|
||||
{{ rougail.proxy.manual.http_proxy.port }}
|
||||
{% endif %}
|
||||
|
||||
|
||||
Depending on the value of the `rougail.proxy.mandatory.use_for_https` variable, this family will appear or disappear (the `hidden` setting line 7). Unlike earlier, this time it is not necessary to use a Jinja function.
|
||||
|
||||
Let's notice that the family is not disabled because the variables will need to remain accessible (yet in `read-only` mode).
|
||||
|
||||
The address and port variables are copied from HTTP to HTTPS if `rougail.proxy.use_for_https` is set to `True`.
|
||||
|
||||
Now let's test all of it:
|
||||
|
||||
>>> from rougail import Rougail, RougailConfig
|
||||
>>> from pprint import pprint
|
||||
>>> RougailConfig['dictionaries_dir'] = ['dict']
|
||||
>>> rougail = Rougail()
|
||||
>>> config = rougail.get_config()
|
||||
>>> config.property.read_only()
|
||||
>>> pprint(config.value.get(), sort_dicts=False)
|
||||
{'rougail.proxy.proxy_mode': 'No proxy'}
|
||||
|
||||
At this time the proxy is not configured yet, so we do not see any variables.
|
||||
Let's look at what happens if we try to access the `rougail.proxy.manual` variable if we are not in manual mode:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> pprint(config.option('rougail.proxy.manual').value.get(), sort_dicts=False)
|
||||
|
||||
We have an error (with the message defined in the Jinja template):
|
||||
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
tiramisu.error.PropertiesOptionError: cannot access to
|
||||
optiondescription "Manual proxy configuration" because
|
||||
has property "disabled" (the mode proxy is not manual)
|
||||
|
||||
|
||||
Let's configure the proxy in manual mode
|
||||
|
||||
>>> config.property.read_write()
|
||||
>>> config.option('rougail.proxy.proxy_mode').value.set('Manual proxy configuration')
|
||||
>>> config.option('rougail.proxy.manual.http_proxy.address').value.set('proxy.example')
|
||||
>>> pprint(config.value.get(), sort_dicts=False)
|
||||
|
||||
We can see that the returned variables does have the desired values:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
{'rougail.proxy.proxy_mode': 'Manual proxy configuration',
|
||||
'rougail.proxy.manual.http_proxy.address': 'proxy.example',
|
||||
'rougail.proxy.manual.http_proxy.port': '8080',
|
||||
'rougail.proxy.manual.use_for_https': True}
|
||||
|
||||
Let's set the `read_only` mode and have a look at the configuration again:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> config.property.read_only()
|
||||
>>> pprint(config.value.get(), sort_dicts=False)
|
||||
{'rougail.proxy.proxy_mode': 'Manual proxy configuration',
|
||||
'rougail.proxy.manual.http_proxy.address': 'proxy.example',
|
||||
'rougail.proxy.manual.http_proxy.port': '8080',
|
||||
'rougail.proxy.manual.use_for_https': True,
|
||||
'rougail.proxy.manual.ssl_proxy.address': 'proxy.example',
|
||||
'rougail.proxy.manual.ssl_proxy.port': '8080'}
|
||||
|
||||
In the `read_only` mode, we can see that the HTTPS configuration appears.
|
||||
|
||||
.. note:: We can see that `rougail.proxy.manual.http_proxy` values have been copied
|
||||
in `rougail.proxy.manual.ssl_proxy` too.
|
||||
|
||||
Changing values programmatically
|
||||
--------------------------------------
|
||||
|
||||
We are going to use the :term:`Tiramisu` API to manipulate programmatically the different variables.
|
||||
|
||||
First, let's set `rougail.proxy.manual.use_for_https` to `False`. It is now possible
|
||||
to configure the HTTPS:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> config.property.read_write()
|
||||
>>> config.option('rougail.proxy.manual.use_for_https').value.set(False)
|
||||
>>> config.option('rougail.proxy.manual.ssl_proxy.address').value.set('other.proxy.example')
|
||||
>>> pprint(config.value.get(), sort_dicts=False)
|
||||
{'rougail.proxy.proxy_mode': 'Manual proxy configuration',
|
||||
'rougail.proxy.manual.http_proxy.address': 'proxy.example',
|
||||
'rougail.proxy.manual.http_proxy.port': '8080',
|
||||
'rougail.proxy.manual.use_for_https': False,
|
||||
'rougail.proxy.manual.ssl_proxy.address': 'other.proxy.example',
|
||||
'rougail.proxy.manual.ssl_proxy.port': '8080'}
|
||||
|
||||
The value of the variable `rougail.proxy.manual.ssl_proxy.address` has actually been modified.
|
||||
But if this variable is hidden again, then the value comes back to the default value:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> config.option('rougail.proxy.manual.use_for_https').value.set(False)
|
||||
>>> config.property.read_only()
|
||||
>>> pprint(config.value.get(), sort_dicts=False)
|
||||
{'rougail.proxy.proxy_mode': 'Manual proxy configuration',
|
||||
'rougail.proxy.manual.http_proxy.address': 'proxy.example',
|
||||
'rougail.proxy.manual.http_proxy.port': '8080',
|
||||
'rougail.proxy.manual.use_for_https': False,
|
||||
'rougail.proxy.manual.ssl_proxy.address': 'proxy.example',
|
||||
'rougail.proxy.manual.ssl_proxy.port': '8080'}
|
||||
|
||||
SOCK's proxy configuration
|
||||
-------------------------------
|
||||
|
||||
Let's add a new :term:`subfamily` named `socks_proxy` with the `address`,
|
||||
`port` and `version` variables.
|
||||
|
||||
Let's create the :file:`dict/06-proxy_manual_socks_proxy.yml` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: the :file:`dict/06-proxy_manual_socks_proxy.yml` file
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
proxy:
|
||||
manual:
|
||||
socks_proxy:
|
||||
description: SOCKS Proxy
|
||||
address:
|
||||
description: SOCKS Address
|
||||
type: domainname
|
||||
port:
|
||||
description: SOCKS Port
|
||||
type: port
|
||||
version:
|
||||
description: SOCKS host version used by proxy
|
||||
type: choice
|
||||
choices:
|
||||
- v4
|
||||
- v5
|
||||
default: v5
|
||||
|
||||
There's nothing new to learn with this file.
|
||||
|
||||
The automatic detection mode
|
||||
------------------------------
|
||||
|
||||
Let's add a new variable named `auto`.
|
||||
|
||||
Let's create the :file:`dict/07-proxy_auto.yml` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: the :file:`dict/07-proxy_auto.yml` file
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
proxy:
|
||||
auto:
|
||||
type: web_address
|
||||
description: Automatic proxy configuration URL
|
||||
disabled:
|
||||
type: jinja
|
||||
jinja: |
|
||||
{% if rougail.proxy.proxy_mode != 'Automatic proxy configuration URL' %}
|
||||
the proxy mode is not automatic
|
||||
{% endif %}
|
||||
|
||||
The `web_address` type imposes a value starting with `http://` or `https://`.
|
||||
This variable is activated when the proxy is in automatic mode.
|
||||
|
||||
The proxy's exceptions
|
||||
---------------------------
|
||||
|
||||
Finally, let's add a variable containing proxy exceptions.
|
||||
|
||||
Let's create the :file:`dict/07-proxy_no_proxy.yml` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: the :file:`dict/07-proxy_no_proxy.yml` file
|
||||
:linenos:
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
proxy:
|
||||
no_proxy:
|
||||
description: Address for which proxy will be desactivated
|
||||
multi: true
|
||||
type: "domainname"
|
||||
params:
|
||||
allow_ip: true
|
||||
allow_cidr_network: true
|
||||
allow_without_dot: true
|
||||
allow_startswith_dot: true
|
||||
disabled:
|
||||
type: jinja
|
||||
jinja: |
|
||||
{% if rougail.proxy.proxy_mode == 'No proxy' %}
|
||||
proxy mode is no proxy
|
||||
{% endif %}
|
||||
mandatory: false
|
||||
|
||||
This `no_proxy` variable is much like a `domainname` type except that we add
|
||||
a `params` line 7, we authorize the :
|
||||
|
||||
- IP
|
||||
- CIDR networks
|
||||
- machine names (without `'.'`)
|
||||
- sub-domaines like `.example`
|
||||
|
||||
There can be multiple exceptions to the proxy, so the variable is :term:`multi` (line5).
|
||||
This variable is only accessible if no proxy is defined (`disabled`).
|
||||
|
||||
.. glossary::
|
||||
|
||||
multi
|
||||
|
||||
A multi is a multiple variable, that is a variable that can have multiple values.
|
||||
|
||||
|
||||
The `no_proxy` variable do not requires a value (that is, `None` is an option),
|
||||
there is line 19 this statement `mandatory: false` which means that this variable is not mandatory.
|
||||
|
||||
|
||||
Let's test it:
|
||||
|
||||
|
||||
>>> from rougail import Rougail, RougailConfig
|
||||
>>> from pprint import pprint
|
||||
>>> RougailConfig['dictionaries_dir'] = ['dict']
|
||||
>>> rougail = Rougail()
|
||||
>>> config = rougail.get_config()
|
||||
>>> config.property.read_write()
|
||||
>>> config.option('rougail.proxy.proxy_mode').value.set('Manual proxy configuration')
|
||||
>>> config.option('rougail.proxy.manual.http_proxy.address').value.set('proxy.example')
|
||||
>>> config.option('rougail.proxy.no_proxy').value.set(['.example', '192.168.1.1'])
|
||||
>>> config.property.read_only()
|
||||
>>> pprint(config.value.get(), sort_dicts=False)
|
||||
|
||||
It outputs:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
{'rougail.proxy.proxy_mode': 'Manual proxy configuration',
|
||||
'rougail.proxy.manual.http_proxy.address': 'proxy.example',
|
||||
'rougail.proxy.manual.http_proxy.port': '8080',
|
||||
'rougail.proxy.manual.use_for_https': True,
|
||||
'rougail.proxy.manual.ssl_proxy.address': 'proxy.example',
|
||||
'rougail.proxy.manual.ssl_proxy.port': '8080',
|
||||
'rougail.proxy.manual.socks_proxy.address': None,
|
||||
'rougail.proxy.manual.socks_proxy.port': None,
|
||||
'rougail.proxy.manual.socks_proxy.version': 'v5',
|
||||
'rougail.proxy.no_proxy': ['.example', '192.168.1.1']}
|
||||
|
||||
But not possible to put an invalid value:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> config.option('rougail.proxy.no_proxy').value.set(['.example', '192.168.1.1', 'not valid'])
|
||||
[..]
|
||||
tiramisu.error.ValueOptionError: "not valid" is an invalid domain name for "Address for which proxy will be desactivated", could be a IP, otherwise must start with lowercase characters followed by lowercase characters, number, "-" and "." characters are allowed
|
||||
|
||||
|
||||
The authentification request
|
||||
--------------------------------
|
||||
|
||||
Nothing special when creating the authentication request. To do this, let's create a `dict/08-proxy_prompt_authentication.yml` file:
|
||||
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: the :file:`dict/08-proxy_prompt_authentication.yml` file
|
||||
:linenos:
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
proxy:
|
||||
prompt_authentication:
|
||||
description: Prompt for authentication if password is saved
|
||||
type: boolean
|
||||
default: true
|
||||
disabled:
|
||||
type: jinja
|
||||
jinja: |
|
||||
{% if rougail.proxy.proxy_mode == 'No proxy' %}
|
||||
proxy mode is no proxy
|
||||
{% endif %}
|
||||
|
||||
The proxy SOCKS v5's DNS
|
||||
------------------------------
|
||||
|
||||
The DNS variable for the SOCKS v5 proxy only appears if the proxy is configured and the version of the SOCKS proxy selected is `v5`.
|
||||
|
||||
Let's create a `dict/09-proxy_proxy_dns_socks5.yml` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: the :file:`dict/09-proxy_proxy_dns_socks5.yml` file
|
||||
:linenos:
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
proxy:
|
||||
proxy_dns_socks5:
|
||||
description: Use proxy DNS when using SOCKS v5
|
||||
type: boolean
|
||||
default: false
|
||||
disabled:
|
||||
type: jinja
|
||||
params:
|
||||
socks_version:
|
||||
type: variable
|
||||
variable: rougail.proxy.manual.socks_proxy.version
|
||||
propertyerror: false
|
||||
jinja: |
|
||||
{% if rougail.proxy.proxy_mode == 'No proxy' %}
|
||||
the proxy mode is no proxy
|
||||
{% elif socks_version is undefined or socks_version == 'v4' %}
|
||||
socks version is v4
|
||||
{% endif %}
|
||||
|
||||
The difficulty here is that the `rougail.proxy.manual.socks_proxy.version` variable
|
||||
can be deactivated (and therefore not usable in a calculation).
|
||||
|
||||
.. FIXME definir ce qu'est une calculation
|
||||
|
||||
In this case, we will add a parameter (here called `socks_version`) which will contain,
|
||||
if there is no property error, the value of the variable.
|
||||
Otherwise the parameter will not be passed to the Jinja template.
|
||||
|
||||
This is why it is necessary to test in the Jinja template whether the `socks_version` variable really exists.
|
||||
|
||||
The DNS over HTTPS
|
||||
----------------------
|
||||
|
||||
Finally we will configure DNS over HTTPS in the 10-proxy_dns_over_https.yml file:
|
||||
|
||||
Let's create a `dict/10-proxy_dns_over_https.yml` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: the :file:`dict/10-proxy_dns_over_https.yml` file
|
||||
:linenos:
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
proxy:
|
||||
dns_over_https:
|
||||
description: DNS over HTTPS
|
||||
enable_dns_over_https:
|
||||
description: Enable DNS over HTTPS
|
||||
type: boolean
|
||||
default: false
|
||||
provider:
|
||||
description: Use Provider
|
||||
type: choice
|
||||
choices:
|
||||
- Cloudflare
|
||||
- NextDNS
|
||||
- Custom
|
||||
default: Cloudflare
|
||||
disabled:
|
||||
type: jinja
|
||||
jinja: |
|
||||
{% if not rougail.proxy.dns_over_https.enable_dns_over_https %}
|
||||
Enable DNS over HTTPS is False
|
||||
{% endif %}
|
||||
custom_dns_url:
|
||||
description: Custom DNS URL
|
||||
type: web_address
|
||||
disabled:
|
||||
type: jinja
|
||||
params:
|
||||
provider:
|
||||
type: variable
|
||||
variable: rougail.proxy.dns_over_https.provider
|
||||
propertyerror: false
|
||||
jinja: |
|
||||
{% if provider is not defined or provider != 'Custom' %}
|
||||
provider is not custom
|
||||
{% endif %}
|
||||
validators:
|
||||
- type: jinja
|
||||
jinja: |
|
||||
{% if rougail.proxy.dns_over_https.custom_dns_url.startswith('http://') %}
|
||||
only https is allowed
|
||||
{% endif %}
|
||||
|
||||
.. FIXME : define validators
|
||||
|
||||
The only particularity here is that we added additional validation (validators) to the `custom_dns_url` variable. Only an address starting with `https://` is allowed (not `http://`).
|
||||
|
||||
----
|
||||
|
||||
The FoxyProxy type's proxy configuration
|
||||
--------------------------------------------
|
||||
|
||||
Here is now the integration of part of the Firefox FoxyProxy plugin.
|
||||
|
||||
The idea is to have a namespace specific to FoxyProxy and to find in it part of the settings that we will have made in the main namespace.
|
||||
|
||||
This is what the page looks like:
|
||||
|
||||
.. image:: images/foxyproxy.png
|
||||
|
||||
It is possible, in this plugin, to specify an unlimited number of proxies.
|
||||
Our `proxy` family will no longer be of the `family` type as before but of another type : the :term:`leadership` type.
|
||||
|
||||
.. FIXME: expliquer ce qu'est le type leardership
|
||||
|
||||
Here is the complete content of the FoxyProxy type proxy configuration
|
||||
(to be put in the `foxyproxy/00-base.yml` file):
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: the :file:``foxyproxy/00-base.yml`` file
|
||||
:linenos:
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
proxy:
|
||||
_type: leadership
|
||||
title:
|
||||
description: Title or Description
|
||||
multi: true
|
||||
color:
|
||||
description: Color
|
||||
type:
|
||||
type: choice
|
||||
choices:
|
||||
- HTTP
|
||||
- HTTPS/SSL
|
||||
- SOCKS5
|
||||
- SOCKS4
|
||||
- PAC URL
|
||||
- WPAD
|
||||
- System (use system settings)
|
||||
- Direct (no proxy)
|
||||
default: Direct (no proxy)
|
||||
address:
|
||||
description: IP address, DNS name, server name
|
||||
multi: true
|
||||
disabled:
|
||||
type: jinja
|
||||
jinja: |
|
||||
{% if foxyproxy.proxy.type not in ['HTTP', 'HTTPS/SSL', 'SOCKS5', 'SOCKS4'] %}
|
||||
proxy does not need address
|
||||
{% endif %}
|
||||
default:
|
||||
type: jinja
|
||||
params:
|
||||
firefox_address:
|
||||
type: variable
|
||||
variable: rougail.proxy.manual.http_proxy.address
|
||||
propertyerror: false
|
||||
jinja: |
|
||||
{% if firefox_address is not undefined %}
|
||||
{{ firefox_address }}
|
||||
{% endif %}
|
||||
port:
|
||||
description: Port
|
||||
type: port
|
||||
default:
|
||||
type: jinja
|
||||
params:
|
||||
firefox_port:
|
||||
type: variable
|
||||
variable: rougail.proxy.manual.http_proxy.port
|
||||
propertyerror: false
|
||||
jinja: |
|
||||
{% if firefox_port is not undefined %}
|
||||
{{ firefox_port }}
|
||||
{% endif %}
|
||||
disabled:
|
||||
type: jinja
|
||||
jinja: |
|
||||
{% if foxyproxy.proxy.type not in ['HTTP', 'HTTPS/SSL', 'SOCKS5', 'SOCKS4'] %}
|
||||
proxy does not need port
|
||||
{% endif %}
|
||||
username:
|
||||
description: Username
|
||||
type: unix_user
|
||||
mandatory:
|
||||
type: jinja
|
||||
jinja: |
|
||||
{% if foxyproxy.proxy.password %}
|
||||
username is mandatory
|
||||
{% endif %}
|
||||
disabled:
|
||||
type: jinja
|
||||
jinja: |
|
||||
{% if foxyproxy.proxy.type not in ['HTTP', 'HTTPS/SSL', 'SOCKS5', 'SOCKS4'] %}
|
||||
proxy does not need username
|
||||
{% endif %}
|
||||
password:
|
||||
description: Password
|
||||
type: secret
|
||||
disabled:
|
||||
type: jinja
|
||||
jinja: |
|
||||
{% if foxyproxy.proxy.type not in ['HTTP', 'HTTPS/SSL', 'SOCKS5', 'SOCKS4'] %}
|
||||
proxy does not need password
|
||||
{% endif %}
|
||||
url:
|
||||
type: web_address
|
||||
disabled:
|
||||
type: jinja
|
||||
jinja: |
|
||||
{% if foxyproxy.proxy.type not in ['PAC URL', 'WPAD'] %}
|
||||
proxy does not need url
|
||||
{% endif %}
|
||||
|
||||
|
||||
A few comments:
|
||||
|
||||
- in the `foxyproxy.proxy` :term:`leader` family there is a variable named `type` (line 4), this may conflict with the `type` attribute (specified line 10). In this case, to specify the type we use the `_type` attribute
|
||||
- a :term:`follower` variable can also be multiple
|
||||
(which is the case for `foxyproxy.proxy.address`)
|
||||
- `foxyproxy.proxy.username` (line 62) becomes :term:`mandatory` if `foxyproxy.proxy.password`
|
||||
is specified, in fact a password without a username is meaningless
|
||||
|
||||
Let's test it:
|
||||
|
||||
>>> from rougail import Rougail, RougailConfig
|
||||
>>> from pprint import pprint
|
||||
>>> RougailConfig['dictionaries_dir'] = ['dict']
|
||||
>>> RougailConfig['extra_dictionaries']['foxyproxy'] = ['foxyproxy/']
|
||||
>>> rougail = Rougail()
|
||||
>>> config = rougail.get_config()
|
||||
>>> config.option('rougail.proxy.proxy_mode').value.set('Manual proxy configuration')
|
||||
>>> config.option('rougail.proxy.manual.http_proxy.address').value.set('proxy.example')
|
||||
>>> config.option('foxyproxy.proxy.title').value.set(['MyProxy'])
|
||||
>>> config.option('foxyproxy.proxy.type', 0).value.set('HTTP')
|
||||
>>> config.option('foxyproxy.proxy.color', 0).value.set('#00000')
|
||||
>>> config.property.read_only()
|
||||
>>> pprint(config.value.get(), sort_dicts=False)
|
||||
|
||||
The output is:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
{'rougail.proxy.proxy_mode': 'Manual proxy configuration',
|
||||
'rougail.proxy.manual.http_proxy.address': 'proxy.example',
|
||||
'rougail.proxy.manual.http_proxy.port': '8080',
|
||||
'rougail.proxy.manual.use_for_https': True,
|
||||
'rougail.proxy.manual.ssl_proxy.address': 'proxy.example',
|
||||
'rougail.proxy.manual.ssl_proxy.port': '8080',
|
||||
'rougail.proxy.manual.socks_proxy.address': None,
|
||||
'rougail.proxy.manual.socks_proxy.port': None,
|
||||
'rougail.proxy.manual.socks_proxy.version': 'v5',
|
||||
'rougail.proxy.no_proxy': [],
|
||||
'rougail.proxy.proxy_dns_socks5': False,
|
||||
'rougail.proxy.dns_over_https.enable_dns_over_https': False,
|
||||
'foxyproxy.proxy.title': [{'foxyproxy.proxy.title': 'MyProxy',
|
||||
'foxyproxy.proxy.color': '#00000',
|
||||
'foxyproxy.proxy.type': 'HTTP',
|
||||
'foxyproxy.proxy.address': ['proxy.example'],
|
||||
'foxyproxy.proxy.port': '8080',
|
||||
'foxyproxy.proxy.username': None,
|
||||
'foxyproxy.proxy.password': None}]}
|
||||
|
||||
The choice we made here is to make `foxyproxy.proxy.username` :term:`mandatory` if a password is specified in the `foxyproxy.proxy.password` variable.
|
||||
|
||||
It makes sense to have a username without a password (in this case the password will be requested when connecting to the proxy). But the opposite does not make sense.
|
||||
|
||||
From a user point of view this may seem disturbing (if you enter the password, you have to return to the previous option to specify the password).
|
||||
|
||||
It is possible to reverse the logic. If the `foxyproxy.proxy.username` variable is set, the `foxyproxy.proxy.password` variable becomes editable.
|
||||
|
||||
None of this two variables needs to be :term:`mandatory`.
|
||||
|
||||
If you prefer this option, here is a second extra dictionary :file:`foxyproxy/01-redefine.yml` which will redefine the behavior only of the `foxyproxy.proxy.username` and `foxyproxy.proxy.password` variables:
|
||||
|
||||
|
||||
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: the :file:`foxyproxy/01-redefine.yml` file
|
||||
:linenos:
|
||||
|
||||
---
|
||||
version: '1.1'
|
||||
proxy:
|
||||
username:
|
||||
redefine: true
|
||||
# suppress mandatory constrainte
|
||||
mandatory: false
|
||||
password:
|
||||
redefine: true
|
||||
hidden:
|
||||
type: jinja
|
||||
jinja: |
|
||||
{% if not foxyproxy.proxy.username %}
|
||||
no username defined
|
||||
{% endif %}
|
||||
|
||||
|
||||
**It's up to you to play now !**
|
|
@ -31,5 +31,6 @@ At first glance we have a choice between five variables:
|
|||
:titlesonly:
|
||||
:caption: The firefox tutorial steps
|
||||
|
||||
preliminary
|
||||
tutorial
|
||||
|
||||
|
|
12
docs/tutorial/preliminary.rst
Normal file
12
docs/tutorial/preliminary.rst
Normal file
|
@ -0,0 +1,12 @@
|
|||
Preliminaries
|
||||
================
|
||||
|
||||
.. prerequisites:: Prerequisistes
|
||||
|
||||
You need to know how to:
|
||||
|
||||
- manipulate a rougail :term:`dictionary`
|
||||
- use a rougail format version
|
||||
- use the rougail command line
|
||||
|
||||
|
Loading…
Reference in a new issue