[PATCH RFC] configoptions: introduce registrar for config options

2017-03-12 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1489346234 25200
#  Sun Mar 12 12:17:14 2017 -0700
# Node ID dd26bc2a3056879181851aaa3ff4accbfc42e1ad
# Parent  62939e0148f170b67ca8c7374f36c413b67fd387
configoptions: introduce registrar for config options

Various talks at the sprint have revolved around establishing more
formalization around config options. Specific problems we'd like
to solve or are thinking about solving include:

* Experimental config options not documented and are not discoverable
  to end-users.
* Config options aren't strongly typed (it depends how they are
  accessed).
* Config options for extensions don't appear in `hg help config`.
* There is no formal mechanism to map a config option to command
  argument behavior. e.g. have a config option imply a command
  argument. Instead, logic is done in the command implementation,
  which results in inconsistent behavior, error messages, weird
  `hg help ` output.
* Config option validation is done at the call site and not as part
  of config loading or command dispatching.
* Config options are declared by side-effect all over the repo. It
  might be nicer to have a single "registry" so the full context of
  all options is easily referenced.
* No mechanism to "alias" an old config option to a new one. e.g.
  carrying over "experimental.feature" to its final value.

This patch introduces a very eary proof of concept for improving
the situation. It adds config options to the "registrar" mechanism,
which allows their declaration to be formalized and recorded in
a central location. This is conceptually similar to populating a
central dict with the data. I chose to use decorators and (for now)
empty functions for declaring config options. This allows docstrings
to be used for writing the config help.

In the future, one could imagine actually calling the function
declaring the config option. It could receive a ui instance and
an object defining the command being invoked. The function could
then look for conflicting options, adjust command arguments, etc.
It could do so in a way that is consistent across commands. e.g.
a ConfigOptionConflict exception could be raised and the ui or
dispatcher could consistently format that error condition rather
than leaving it to individual command functions to raise on their
own.

It's worth noting that we need all the *core* options defined in
a central file because of lazy module loading. If a module isn't
loaded, the config option declarations wouldn't be called!

There are several things missing from this patch and open issues to
resolve:

* i18n of help text
* Actually using docstrings in `hg help`
* Hooking up strong typing or hinted typing
* Figuring out how to declare config options with sub-options
* Better solution for declaring config options that have both global
  options and per-item sub-options (like hostsecurity.ciphers)
* Actually hooking it up to config loading
* Mechanism for declaring config options in extensions

diff --git a/mercurial/configoptions.py b/mercurial/configoptions.py
new file mode 100644
--- /dev/null
+++ b/mercurial/configoptions.py
@@ -0,0 +1,102 @@
+# configoptions.py -- Declaration of configuration options
+#
+# Copyright 2017 Gregory Szorc 
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from . import (
+registrar,
+)
+
+configoption = registrar.configoption()
+
+@configoption('hostsecurity.ciphers')
+def optionciphers():
+"""Defines the cryptographic ciphers to use for connections.
+
+Value must be a valid OpenSSL Cipher List Format as documented at
+
https://www.openssl.org/docs/manmaster/apps/ciphers.html#CIPHER-LIST-FORMAT.
+
+This setting is for advanced users only. Setting to incorrect values
+can significantly lower connection security or decrease performance.
+You have been warned.
+
+This option requires Python 2.7.
+"""
+
+@configoption('hostsecurity.minimumprotocol')
+def optionminimumprotocol():
+"""Defines the minimum channel encryption protocol to use.
+
+By default, the highest version of TLS supported by both client and
+server is used.
+
+Allowed values are: ``tls1.0``, ``tls1.1``, ``tls1.2``.
+
+When running on an old Python version, only ``tls1.0`` is allowed since
+old versions of Python only support up to TLS 1.0.
+
+When running a Python that supports modern TLS versions, the default is
+``tls1.1``. ``tls1.0`` can still be used to allow TLS 1.0. However, this
+weakens security and should only be used as a feature of last resort if
+a server does not support TLS 1.1+.
+"""
+
+@configoption('hostsecurity.*:ciphers')
+def perhostciphers():
+"""Per host version of ``hostsecurity.ciphers``."""
+
+@configoption('hostsecurity.*:fingerprints')
+def perhostfingerprints():
+"""A list of hashes of the DER encoded peer/remote certificate. Values
+have the form ``algorithm`

Re: [PATCH RFC] configoptions: introduce registrar for config options

2017-04-11 Thread Ryan McElroy
Thanks for sending this out and sorry for not paying attention to it for 
so long.


The relevant parts of the sprint discussion, I think, are in the 
sections "Friendly HG Breakout" and " Experimental as a Tag instead of a 
Name" (those are the two places where "registry" came up. There's also 
some related discussion in the " Flags and defaults breakout" breakout, 
but that stuff has mostly been sent in patches by Rodrigo and myself 
already.


I have to take a closer look at this patch and at Jun's immutable config 
stuff to see if these interact at all. I also think that David SP was 
thinking about some config registry stuff as well. I may play with this 
idea during the freeze to see if I can come up with a nice incremental 
conversion as well.


Again, thanks for the RFC. I'll try to dive in deeper soon.

~Ryan


On 3/24/17 5:41 PM, Gregory Szorc wrote:
On Fri, Mar 24, 2017 at 10:24 AM, Martin von Zweigbergk 
mailto:martinv...@google.com>> wrote:


On Sun, Mar 12, 2017 at 12:18 PM, Gregory Szorc
mailto:gregory.sz...@gmail.com>> wrote:
> # HG changeset patch
> # User Gregory Szorc mailto:gregory.sz...@gmail.com>>
> # Date 1489346234 25200
> #  Sun Mar 12 12:17:14 2017 -0700
> # Node ID dd26bc2a3056879181851aaa3ff4accbfc42e1ad
> # Parent  62939e0148f170b67ca8c7374f36c413b67fd387
> configoptions: introduce registrar for config options

I like the direction. I missed the discussion at the sprint. Was the
consensus that this is the way to go?


There were some side discussions. Not anything formal IIRC.


What's the next step? Will you send a non-RFC series adding a few
users as well? I'm also curious to see the "Actually hooking it up to
config loading" step.


I have no plans to work on this.

I put the RFC out there because there were a number of conversations 
around overhauling configs and I wanted a tangible prototype for a 
formal config declaration mechanism to be in people's minds so they 
could consider benefits that a more formal config mechanism would 
have. (I think it can solve a lot of problems around things like 
environment variable mappings, config aliases, stronger type checking, 
mapping configs to command arguments, etc.)



>
> Various talks at the sprint have revolved around establishing more
> formalization around config options. Specific problems we'd like
> to solve or are thinking about solving include:
>
> * Experimental config options not documented and are not
discoverable
>   to end-users.
> * Config options aren't strongly typed (it depends how they are
>   accessed).
> * Config options for extensions don't appear in `hg help config`.
> * There is no formal mechanism to map a config option to command
>   argument behavior. e.g. have a config option imply a command
>   argument. Instead, logic is done in the command implementation,
>   which results in inconsistent behavior, error messages, weird
>   `hg help ` output.
> * Config option validation is done at the call site and not as part
>   of config loading or command dispatching.
> * Config options are declared by side-effect all over the repo. It
>   might be nicer to have a single "registry" so the full context of
>   all options is easily referenced.
> * No mechanism to "alias" an old config option to a new one. e.g.
>   carrying over "experimental.feature" to its final value.
>
> This patch introduces a very eary proof of concept for improving
> the situation. It adds config options to the "registrar" mechanism,
> which allows their declaration to be formalized and recorded in
> a central location. This is conceptually similar to populating a
> central dict with the data. I chose to use decorators and (for now)
> empty functions for declaring config options. This allows docstrings
> to be used for writing the config help.
>
> In the future, one could imagine actually calling the function
> declaring the config option. It could receive a ui instance and
> an object defining the command being invoked. The function could
> then look for conflicting options, adjust command arguments, etc.
> It could do so in a way that is consistent across commands. e.g.
> a ConfigOptionConflict exception could be raised and the ui or
> dispatcher could consistently format that error condition rather
> than leaving it to individual command functions to raise on their
> own.
>
> It's worth noting that we need all the *core* options defined in
> a central file because of lazy module loading. If a module isn't
> loaded, the config option declarations wouldn't be called!
>
> There are several things missing from this patch and open issues to
> resolve:
>
> * i18n of help text
> * Actually using docstrings in `hg help`
> * Hooking up strong typing or hinted typing
> * Figurin

Re: [PATCH RFC] configoptions: introduce registrar for config options

2017-03-24 Thread Martin von Zweigbergk via Mercurial-devel
On Sun, Mar 12, 2017 at 12:18 PM, Gregory Szorc  wrote:
> # HG changeset patch
> # User Gregory Szorc 
> # Date 1489346234 25200
> #  Sun Mar 12 12:17:14 2017 -0700
> # Node ID dd26bc2a3056879181851aaa3ff4accbfc42e1ad
> # Parent  62939e0148f170b67ca8c7374f36c413b67fd387
> configoptions: introduce registrar for config options

I like the direction. I missed the discussion at the sprint. Was the
consensus that this is the way to go?

What's the next step? Will you send a non-RFC series adding a few
users as well? I'm also curious to see the "Actually hooking it up to
config loading" step.

>
> Various talks at the sprint have revolved around establishing more
> formalization around config options. Specific problems we'd like
> to solve or are thinking about solving include:
>
> * Experimental config options not documented and are not discoverable
>   to end-users.
> * Config options aren't strongly typed (it depends how they are
>   accessed).
> * Config options for extensions don't appear in `hg help config`.
> * There is no formal mechanism to map a config option to command
>   argument behavior. e.g. have a config option imply a command
>   argument. Instead, logic is done in the command implementation,
>   which results in inconsistent behavior, error messages, weird
>   `hg help ` output.
> * Config option validation is done at the call site and not as part
>   of config loading or command dispatching.
> * Config options are declared by side-effect all over the repo. It
>   might be nicer to have a single "registry" so the full context of
>   all options is easily referenced.
> * No mechanism to "alias" an old config option to a new one. e.g.
>   carrying over "experimental.feature" to its final value.
>
> This patch introduces a very eary proof of concept for improving
> the situation. It adds config options to the "registrar" mechanism,
> which allows their declaration to be formalized and recorded in
> a central location. This is conceptually similar to populating a
> central dict with the data. I chose to use decorators and (for now)
> empty functions for declaring config options. This allows docstrings
> to be used for writing the config help.
>
> In the future, one could imagine actually calling the function
> declaring the config option. It could receive a ui instance and
> an object defining the command being invoked. The function could
> then look for conflicting options, adjust command arguments, etc.
> It could do so in a way that is consistent across commands. e.g.
> a ConfigOptionConflict exception could be raised and the ui or
> dispatcher could consistently format that error condition rather
> than leaving it to individual command functions to raise on their
> own.
>
> It's worth noting that we need all the *core* options defined in
> a central file because of lazy module loading. If a module isn't
> loaded, the config option declarations wouldn't be called!
>
> There are several things missing from this patch and open issues to
> resolve:
>
> * i18n of help text
> * Actually using docstrings in `hg help`
> * Hooking up strong typing or hinted typing
> * Figuring out how to declare config options with sub-options
> * Better solution for declaring config options that have both global
>   options and per-item sub-options (like hostsecurity.ciphers)
> * Actually hooking it up to config loading
> * Mechanism for declaring config options in extensions
>
> diff --git a/mercurial/configoptions.py b/mercurial/configoptions.py
> new file mode 100644
> --- /dev/null
> +++ b/mercurial/configoptions.py
> @@ -0,0 +1,102 @@
> +# configoptions.py -- Declaration of configuration options
> +#
> +# Copyright 2017 Gregory Szorc 
> +#
> +# This software may be used and distributed according to the terms of the
> +# GNU General Public License version 2 or any later version.
> +
> +from . import (
> +registrar,
> +)
> +
> +configoption = registrar.configoption()
> +
> +@configoption('hostsecurity.ciphers')
> +def optionciphers():
> +"""Defines the cryptographic ciphers to use for connections.
> +
> +Value must be a valid OpenSSL Cipher List Format as documented at
> +
> https://www.openssl.org/docs/manmaster/apps/ciphers.html#CIPHER-LIST-FORMAT.
> +
> +This setting is for advanced users only. Setting to incorrect values
> +can significantly lower connection security or decrease performance.
> +You have been warned.
> +
> +This option requires Python 2.7.
> +"""
> +
> +@configoption('hostsecurity.minimumprotocol')
> +def optionminimumprotocol():
> +"""Defines the minimum channel encryption protocol to use.
> +
> +By default, the highest version of TLS supported by both client and
> +server is used.
> +
> +Allowed values are: ``tls1.0``, ``tls1.1``, ``tls1.2``.
> +
> +When running on an old Python version, only ``tls1.0`` is allowed since
> +old versions of Python only support up to TLS 1.0.
> +
> +When running a Python that supports modern TLS 

Re: [PATCH RFC] configoptions: introduce registrar for config options

2017-03-24 Thread Gregory Szorc
On Fri, Mar 24, 2017 at 10:24 AM, Martin von Zweigbergk <
martinv...@google.com> wrote:

> On Sun, Mar 12, 2017 at 12:18 PM, Gregory Szorc 
> wrote:
> > # HG changeset patch
> > # User Gregory Szorc 
> > # Date 1489346234 25200
> > #  Sun Mar 12 12:17:14 2017 -0700
> > # Node ID dd26bc2a3056879181851aaa3ff4accbfc42e1ad
> > # Parent  62939e0148f170b67ca8c7374f36c413b67fd387
> > configoptions: introduce registrar for config options
>
> I like the direction. I missed the discussion at the sprint. Was the
> consensus that this is the way to go?
>

There were some side discussions. Not anything formal IIRC.


>
> What's the next step? Will you send a non-RFC series adding a few
> users as well? I'm also curious to see the "Actually hooking it up to
> config loading" step.
>

I have no plans to work on this.

I put the RFC out there because there were a number of conversations around
overhauling configs and I wanted a tangible prototype for a formal config
declaration mechanism to be in people's minds so they could consider
benefits that a more formal config mechanism would have. (I think it can
solve a lot of problems around things like environment variable mappings,
config aliases, stronger type checking, mapping configs to command
arguments, etc.)


>
> >
> > Various talks at the sprint have revolved around establishing more
> > formalization around config options. Specific problems we'd like
> > to solve or are thinking about solving include:
> >
> > * Experimental config options not documented and are not discoverable
> >   to end-users.
> > * Config options aren't strongly typed (it depends how they are
> >   accessed).
> > * Config options for extensions don't appear in `hg help config`.
> > * There is no formal mechanism to map a config option to command
> >   argument behavior. e.g. have a config option imply a command
> >   argument. Instead, logic is done in the command implementation,
> >   which results in inconsistent behavior, error messages, weird
> >   `hg help ` output.
> > * Config option validation is done at the call site and not as part
> >   of config loading or command dispatching.
> > * Config options are declared by side-effect all over the repo. It
> >   might be nicer to have a single "registry" so the full context of
> >   all options is easily referenced.
> > * No mechanism to "alias" an old config option to a new one. e.g.
> >   carrying over "experimental.feature" to its final value.
> >
> > This patch introduces a very eary proof of concept for improving
> > the situation. It adds config options to the "registrar" mechanism,
> > which allows their declaration to be formalized and recorded in
> > a central location. This is conceptually similar to populating a
> > central dict with the data. I chose to use decorators and (for now)
> > empty functions for declaring config options. This allows docstrings
> > to be used for writing the config help.
> >
> > In the future, one could imagine actually calling the function
> > declaring the config option. It could receive a ui instance and
> > an object defining the command being invoked. The function could
> > then look for conflicting options, adjust command arguments, etc.
> > It could do so in a way that is consistent across commands. e.g.
> > a ConfigOptionConflict exception could be raised and the ui or
> > dispatcher could consistently format that error condition rather
> > than leaving it to individual command functions to raise on their
> > own.
> >
> > It's worth noting that we need all the *core* options defined in
> > a central file because of lazy module loading. If a module isn't
> > loaded, the config option declarations wouldn't be called!
> >
> > There are several things missing from this patch and open issues to
> > resolve:
> >
> > * i18n of help text
> > * Actually using docstrings in `hg help`
> > * Hooking up strong typing or hinted typing
> > * Figuring out how to declare config options with sub-options
> > * Better solution for declaring config options that have both global
> >   options and per-item sub-options (like hostsecurity.ciphers)
> > * Actually hooking it up to config loading
> > * Mechanism for declaring config options in extensions
> >
> > diff --git a/mercurial/configoptions.py b/mercurial/configoptions.py
> > new file mode 100644
> > --- /dev/null
> > +++ b/mercurial/configoptions.py
> > @@ -0,0 +1,102 @@
> > +# configoptions.py -- Declaration of configuration options
> > +#
> > +# Copyright 2017 Gregory Szorc 
> > +#
> > +# This software may be used and distributed according to the terms of
> the
> > +# GNU General Public License version 2 or any later version.
> > +
> > +from . import (
> > +registrar,
> > +)
> > +
> > +configoption = registrar.configoption()
> > +
> > +@configoption('hostsecurity.ciphers')
> > +def optionciphers():
> > +"""Defines the cryptographic ciphers to use for connections.
> > +
> > +Value must be a valid OpenSSL Cipher List Format as documented at
> > +h