From ba079ad7c1af397e4a2167ad00680a39dbdc7ba4 Mon Sep 17 00:00:00 2001 From: BJ Dierkes Date: Mon, 16 Jul 2012 00:52:28 -0500 Subject: [PATCH] Resolves Issue #136 --- ChangeLog | 5 ++++- cement/core/foundation.py | 31 ++++++++++++++++---------- doc/source/dev/configuration.rst | 13 +++++++---- tests/core/config_tests.py | 37 +++++++++++++++++++++++++++++--- 4 files changed, 67 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0d789f11..5dfa9553 100755 --- a/ChangeLog +++ b/ChangeLog @@ -44,7 +44,10 @@ Incompatible Changes: live in the same file (i.e. hooks won't be registered just because you imported an extension to sub-class a handler, etc). * cement.utils.test_helper moved to cement.utils.test. - + * By default, command line arguments no longer override config settings. + This is now configurable by the CementApp.Meta.arguments_override_config + boolean. + 1.9.12 - Thu Jul 05, 2012 ------------------------------------------------------------------------------ diff --git a/cement/core/foundation.py b/cement/core/foundation.py index 6897551a..fc08c980 100644 --- a/cement/core/foundation.py +++ b/cement/core/foundation.py @@ -75,6 +75,13 @@ class CementApp(meta.MetaMixin): and options. Default: sys.argv[1:] + + arguments_override_config + A boolean to toggle whether command line arguments should + override configuration values if the argument name matches the + config key. I.e. --foo=bar would override config['myapp']['foo']. + + Default: False config_section The base configuration section for the application. @@ -310,6 +317,7 @@ class CementApp(meta.MetaMixin): plugin_bootstrap = None plugin_dir = None argv = list(sys.argv[1:]) + arguments_override_config = False config_section = None config_defaults = None catch_signals = [signal.SIGTERM, signal.SIGINT] @@ -585,19 +593,20 @@ class CementApp(meta.MetaMixin): def _parse_args(self): self.args.parse(self.argv) - for member in dir(self.args.parsed_args): - if member and member.startswith('_'): - continue + if self._meta.arguments_override_config is True: + for member in dir(self.args.parsed_args): + if member and member.startswith('_'): + continue - # don't override config values for options that weren't passed - # or in otherwords are None - elif getattr(self.args.parsed_args, member) is None: - continue + # don't override config values for options that weren't passed + # or in otherwords are None + elif getattr(self.args.parsed_args, member) is None: + continue - for section in self.config.get_sections(): - if member in self.config.keys(section): - self.config.set(section, member, - getattr(self.args.parsed_args, member)) + for section in self.config.get_sections(): + if member in self.config.keys(section): + self.config.set(section, member, + getattr(self.args.parsed_args, member)) def _setup_signals(self): if not self._meta.catch_signals: diff --git a/doc/source/dev/configuration.rst b/doc/source/dev/configuration.rst index dfe68975..356a168b 100644 --- a/doc/source/dev/configuration.rst +++ b/doc/source/dev/configuration.rst @@ -32,7 +32,8 @@ is the order in which configurations are discovered: * Extended by any handler Meta.config_defaults (not overridden) * Overridden by a config_defaults dict passed to foundation.CementApp() * Overridden by the configuration files - * Overridden by command line options that match the same key name + * Overridden by command line options that match the same key name (only + if CementApp.Meta.arguments_override_config=True) Application Default Settings @@ -213,8 +214,9 @@ If no config_files meta data is provided, Cement will set the defaults to: Overriding Configurations with Command Line Options --------------------------------------------------- -Config settings are automatically overridden if a passed command line option -matches the name. Note that this happens in *all* sections: +Config settings can be automatically overridden by a passed command line +option if the argument name matches a configuration key. Note that this will +happen in *all* config sections: .. code-block:: python @@ -223,7 +225,10 @@ matches the name. Note that this happens in *all* sections: defaults = backend.defaults('base') defaults['base']['foo'] = 'bar' - app = foundation.CementApp('myapp', config_defaults=defaults) + app = foundation.CementApp('myapp', + config_defaults=defaults, + arguments_override_config=True, + ) try: # First setup the application app.setup() diff --git a/tests/core/config_tests.py b/tests/core/config_tests.py index 000b5912..4d797fcb 100644 --- a/tests/core/config_tests.py +++ b/tests/core/config_tests.py @@ -27,11 +27,42 @@ class ConfigTestCase(test.CementTestCase): defaults = dict() defaults['test'] = dict() defaults['test']['debug'] = False - self.app = self.make_app(config_defaults=defaults, argv=['--debug']) + defaults['test']['foo'] = 'bar' + + # first test that it doesn't override the config with the default + # setting of arguments_override_config=False + self.app = self.make_app( + config_defaults=defaults, + argv=['--foo=not_bar'], + arguments_override_config=False + ) self.app.setup() + self.app.args.add_argument('--foo', action='store') self.app.run() - self.eq(self.app.config.get('test', 'debug'), True) - + self.eq(self.app.config.get('test', 'foo'), 'bar') + + # then make sure that it does + self.app = self.make_app( + config_defaults=defaults, + argv=['--foo=not_bar'], + arguments_override_config=True + ) + self.app.setup() + self.app.args.add_argument('--foo', action='store') + self.app.run() + self.eq(self.app.config.get('test', 'foo'), 'not_bar') + + # one last test just for code coverage + self.app = self.make_app( + config_defaults=defaults, + argv=['--debug'], + arguments_override_config=True + ) + self.app.setup() + self.app.args.add_argument('--foo', action='store') + self.app.run() + self.eq(self.app.config.get('test', 'foo'), 'bar') + def test_parse_file_bad_path(self): self.app._meta.config_files = ['./some_bogus_path'] self.app.setup()