From 90a50f8b51bdd71d9f2b1fd82352628cfd681898 Mon Sep 17 00:00:00 2001 From: Matt Wright Date: Thu, 23 Jan 2014 15:05:37 -0500 Subject: [PATCH] Add `get_namespace` method on `Config` object for convenient access of namespaced config options. --- flask/config.py | 34 ++++++++++++++++++++++++++++++++++ flask/testsuite/config.py | 15 +++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/flask/config.py b/flask/config.py index 07d6fbc8..66bf7eb4 100644 --- a/flask/config.py +++ b/flask/config.py @@ -164,5 +164,39 @@ class Config(dict): if key.isupper(): self[key] = getattr(obj, key) + def get_namespace(self, namespace, lowercase=True): + """Returns a dictionary containing a subset of configuration options + that match the specified namespace/prefix. Example usage:: + + app.config['IMAGE_STORE_TYPE'] = 'fs' + app.config['IMAGE_STORE_PATH'] = '/var/app/images' + app.config['IMAGE_STORE_BASE_URL'] = 'http://img.website.com' + image_store_config = app.config.get_namespace('IMAGE_STORE_') + + The resulting dictionary `image_store` would look like:: + + { + 'type': 'fs', + 'path': '/var/app/images', + 'base_url': 'http://img.website.com' + } + + This is often useful when configuration options map directly to + keyword arguments in functions or class constructors. + + :param namespace: a configuration namespace + :param lowercase: a flag indicating if the keys of the resulting + dictionary should be lowercase + """ + rv = {} + for k, v in self.iteritems(): + if not k.startswith(namespace): + continue + key = k[len(namespace):] + if lowercase: + key = key.lower() + rv[key] = v + return rv + def __repr__(self): return '<%s %s>' % (self.__class__.__name__, dict.__repr__(self)) diff --git a/flask/testsuite/config.py b/flask/testsuite/config.py index cdc6273f..c2c14cb1 100644 --- a/flask/testsuite/config.py +++ b/flask/testsuite/config.py @@ -105,6 +105,21 @@ class ConfigTestCase(FlaskTestCase): app.config['PERMANENT_SESSION_LIFETIME'] = 42 self.assert_equal(app.permanent_session_lifetime.seconds, 42) + def test_get_namespace(self): + app = flask.Flask(__name__) + app.config['FOO_OPTION_1'] = 'foo option 1' + app.config['FOO_OPTION_2'] = 'foo option 2' + app.config['BAR_STUFF_1'] = 'bar stuff 1' + app.config['BAR_STUFF_2'] = 'bar stuff 2' + foo_options = app.config.get_namespace('FOO_') + self.assert_equal(2, len(foo_options)) + self.assert_equal('foo option 1', foo_options['option_1']) + self.assert_equal('foo option 2', foo_options['option_2']) + bar_options = app.config.get_namespace('BAR_', lowercase=False) + self.assert_equal(2, len(bar_options)) + self.assert_equal('bar stuff 1', bar_options['STUFF_1']) + self.assert_equal('bar stuff 2', bar_options['STUFF_2']) + class LimitedLoaderMockWrapper(object): def __init__(self, loader):