diff --git a/oslo_config/cfg.py b/oslo_config/cfg.py index 39615cae..e5edaa8e 100644 --- a/oslo_config/cfg.py +++ b/oslo_config/cfg.py @@ -1776,15 +1776,13 @@ class _Namespace(argparse.Namespace): try: return self._cli[name] except KeyError: - raise AttributeError( - "'_Namespace' object has no attribute '%s'" % name) + return super(_Namespace, self).__getattr__(name) def __delattr__(self, name): try: del self._cli[name] except KeyError: - raise AttributeError( - "'_Namespace' object has no attribute '%s'" % name) + return super(_Namespace, self).__delattr__(name) def _parse_cli_opts_from_config_file(self, sections, normalized): """Parse CLI options from a config file. diff --git a/oslo_config/tests/test_cfg.py b/oslo_config/tests/test_cfg.py index 037d6227..92637ed5 100644 --- a/oslo_config/tests/test_cfg.py +++ b/oslo_config/tests/test_cfg.py @@ -3457,6 +3457,18 @@ class NamespaceTestCase(BaseTestCase): self.assertRaises(AttributeError, self.ns.__getattr__, 'boo') self.assertRaises(AttributeError, self.ns.__delattr__, 'boo') + def test_attrs_subparser(self): + CONF = cfg.ConfigOpts() + CONF.register_cli_opt(cfg.SubCommandOpt( + 'foo', handler=lambda sub: sub.add_parser('foo'))) + CONF(['foo']) + + def test_attrs_subparser_failure(self): + CONF = cfg.ConfigOpts() + CONF.register_cli_opt(cfg.SubCommandOpt( + 'foo', handler=lambda sub: sub.add_parser('foo'))) + self.assertRaises(SystemExit, CONF, ['foo', 'bar']) + class TildeExpansionTestCase(BaseTestCase):