[PATCH RFC] configoptions: introduce registrar for config options
# 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
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
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
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