From c889fbc231af08a0cd28a9694b60ffde9e1ff650 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sun, 9 Jun 2013 12:06:33 +0100 Subject: [PATCH] Changed interface for `flask.g` This now makes it behave like it did before, it's just an object. It did however gain ``__contains__`` and ``__iter__`` and I added a ``get()`` method to fetch an attribute without raising an error. This fixes #759. --- CHANGES | 4 ++++ docs/api.rst | 8 ++++---- flask/ctx.py | 15 ++++++--------- flask/testsuite/basic.py | 21 +++++++++++++++------ 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/CHANGES b/CHANGES index 5a87b701..16f00a2e 100644 --- a/CHANGES +++ b/CHANGES @@ -40,6 +40,10 @@ Release date to be decided. ``flask.json.dumps`` to return bytestrings by default. - ``flask.g`` is now stored on the app context instead of the request context. +- ``flask.g`` now gained a ``get()`` method for not erroring out on non + existing items. +- ``flask.g`` now can be used with the ``in`` operator to see what's defined + and it now is iterable and will yield all attributes stored. - ``flask.Flask.request_globals_class`` got renamed to ``flask.Flask.app_ctx_globals_class`` which is a better name to what it does since 0.10. diff --git a/docs/api.rst b/docs/api.rst index 48f753c4..3eacc5f5 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -276,12 +276,12 @@ thing, like it does for :class:`request` and :class:`session`. is especially useful when combined with the :ref:`faking-resources` pattern for testing. - Additionally as of 0.10 you can use the subscription operator syntax to - get an attribute or `None` if it's not set. These two usages are now - equivalent:: + Additionally as of 0.10 you can use the :meth:`get` method to + get an attribute or `None` (or the second argument) if it's not set. + These two usages are now equivalent:: user = getattr(flask.g, 'user', None) - user = flask.g['user'] + user = flask.g.get('user', None) This is a proxy. See :ref:`notes-on-proxies` for more information. diff --git a/flask/ctx.py b/flask/ctx.py index 19f42047..f1342378 100644 --- a/flask/ctx.py +++ b/flask/ctx.py @@ -24,17 +24,14 @@ from .signals import appcontext_pushed, appcontext_popped class _AppCtxGlobals(object): """A plain object.""" - def __getitem__(self, name): - try: - return getattr(self, name) - except AttributeError: - return None + def get(self, name, default=None): + return self.__dict__.get(name, default) - def __setitem__(self, name, value): - setattr(self, name, value) + def __contains__(self, item): + return item in self.__dict__ - def __delitem__(self, name, value): - delattr(self, name, value) + def __iter__(self): + return iter(self.__dict__) def __repr__(self): top = _app_ctx_stack.top diff --git a/flask/testsuite/basic.py b/flask/testsuite/basic.py index de90bb65..a170f5b0 100644 --- a/flask/testsuite/basic.py +++ b/flask/testsuite/basic.py @@ -1116,18 +1116,27 @@ class BasicFunctionalityTestCase(FlaskTestCase): self.assert_equal(len(errors), 3) self.assert_equal(errors[1], None) - def test_subscript_syntax_on_g(self): + def test_get_method_on_g(self): app = flask.Flask(__name__) app.testing = True with app.app_context(): - self.assert_equal(flask.g['x'], None) + self.assert_equal(flask.g.get('x'), None) + self.assert_equal(flask.g.get('x', 11), 11) flask.g.x = 42 - self.assert_equal(flask.g['x'], 42) + self.assert_equal(flask.g.get('x'), 42) self.assert_equal(flask.g.x, 42) - flask.g['x'] = 23 - self.assert_equal(flask.g['x'], 23) - self.assert_equal(flask.g.x, 23) + + def test_g_iteration_protocol(self): + app = flask.Flask(__name__) + app.testing = True + + with app.app_context(): + flask.g.foo = 23 + flask.g.bar = 42 + self.assert_equal('foo' in flask.g, True) + self.assert_equal('foos' in flask.g, False) + self.assert_equal(sorted(flask.g), ['bar', 'foo']) class SubdomainTestCase(FlaskTestCase):