Browse Source

deprecated init_jinja_globals

pull/262/head
Armin Ronacher 14 years ago
parent
commit
0da56d7f5c
  1. 3
      CHANGES
  2. 50
      flask/app.py
  3. 31
      flask/helpers.py
  4. 20
      tests/flask_tests.py

3
CHANGES

@ -40,6 +40,9 @@ Release date to be announced, codename to be selected
- Added `teardown_request` decorator, for functions that should run at the end
of a request regardless of whether an exception occurred.
- Implemented :func:`flask.has_request_context`
- Deprecated `init_jinja_globals`. Override the
:meth:`~flask.Flask.create_jinja_environment` method instead to
achieve the same functionality.
Version 0.6.1
-------------

50
flask/app.py

@ -24,7 +24,7 @@ from werkzeug.exceptions import HTTPException, InternalServerError, \
MethodNotAllowed
from .helpers import _PackageBoundObject, url_for, get_flashed_messages, \
_tojson_filter, _endpoint_from_view_func
locked_cached_property, _tojson_filter, _endpoint_from_view_func
from .wrappers import Request, Response
from .config import ConfigAttribute, Config
from .ctx import _RequestContext
@ -317,11 +317,6 @@ class Flask(_PackageBoundObject):
endpoint='static',
view_func=self.send_static_file)
#: The Jinja2 environment. It is created from the
#: :attr:`jinja_options`.
self.jinja_env = self.create_jinja_environment()
self.init_jinja_globals()
@property
def propagate_exceptions(self):
"""Returns the value of the `PROPAGATE_EXCEPTIONS` configuration
@ -356,16 +351,43 @@ class Flask(_PackageBoundObject):
self._logger = rv = create_logger(self)
return rv
@locked_cached_property
def jinja_env(self):
"""The Jinja2 environment used to load templates."""
rv = self.create_jinja_environment()
# Hack to support the init_jinja_globals method which is supported
# until 1.0 but has an API deficiency.
if getattr(self.init_jinja_globals, 'im_func', None) is not \
Flask.init_jinja_globals.im_func:
from warnings import warn
warn(DeprecationWarning('This flask class uses a customized '
'init_jinja_globals() method which is deprecated. '
'Move the code from that method into the '
'create_jinja_environment() method instead.'))
self.__dict__['jinja_env'] = rv
self.init_jinja_globals()
return rv
def create_jinja_environment(self):
"""Creates the Jinja2 environment based on :attr:`jinja_options`
and :meth:`select_jinja_autoescape`.
and :meth:`select_jinja_autoescape`. Since 0.7 this also adds
the Jinja2 globals and filters after initialization. Override
this function to customize the behavior.
.. versionadded:: 0.5
"""
options = dict(self.jinja_options)
if 'autoescape' not in options:
options['autoescape'] = self.select_jinja_autoescape
return Environment(loader=self.create_jinja_loader(), **options)
rv = Environment(loader=self.create_jinja_loader(), **options)
rv.globals.update(
url_for=url_for,
get_flashed_messages=get_flashed_messages
)
rv.filters['tojson'] = _tojson_filter
return rv
def create_jinja_loader(self):
"""Creates the loader for the Jinja2 environment. Can be used to
@ -376,17 +398,13 @@ class Flask(_PackageBoundObject):
return _DispatchingJinjaLoader(self)
def init_jinja_globals(self):
"""Called directly after the environment was created to inject
some defaults (like `url_for`, `get_flashed_messages` and the
`tojson` filter.
"""Deprecated. Used to initialize the Jinja2 globals.
.. versionadded:: 0.5
.. versionchanged:: 0.7
This method is deprecated with 0.7. Override
:meth:`create_jinja_environment` instead.
"""
self.jinja_env.globals.update(
url_for=url_for,
get_flashed_messages=get_flashed_messages
)
self.jinja_env.filters['tojson'] = _tojson_filter
def select_jinja_autoescape(self, filename):
"""Returns `True` if autoescaping should be active for the given

31
flask/helpers.py

@ -15,6 +15,7 @@ import posixpath
import mimetypes
from time import time
from zlib import adler32
from threading import RLock
# try to load the best simplejson implementation available. If JSON
# is not installed, we add a failing class.
@ -58,6 +59,10 @@ else:
_tojson_filter = json.dumps
# sentinel
_missing = object()
# what separators does this operating system provide that are not a slash?
# this is used by the send_from_directory function to ensure that nobody is
# able to access files from outside the filesystem.
@ -435,6 +440,32 @@ def _get_package_path(name):
return os.getcwd()
class locked_cached_property(object):
"""A decorator that converts a function into a lazy property. The
function wrapped is called the first time to retrieve the result
and then that calculated result is used the next time you access
the value. Works like the one in Werkzeug but has a lock for
thread safety.
"""
def __init__(self, func, name=None, doc=None):
self.__name__ = name or func.__name__
self.__module__ = func.__module__
self.__doc__ = doc or func.__doc__
self.func = func
self.lock = RLock()
def __get__(self, obj, type=None):
if obj is None:
return self
with self.lock:
value = obj.__dict__.get(self.__name__, _missing)
if value is _missing:
value = self.func(obj)
obj.__dict__[self.__name__] = value
return value
class _PackageBoundObject(object):
def __init__(self, import_name):

20
tests/flask_tests.py

@ -1564,6 +1564,25 @@ class TestSignals(unittest.TestCase):
flask.got_request_exception.disconnect(record, app)
class DeprecationsTestCase(unittest.TestCase):
def test_init_jinja_globals(self):
class MyFlask(flask.Flask):
def init_jinja_globals(self):
self.jinja_env.globals['foo'] = '42'
with catch_warnings() as log:
app = MyFlask(__name__)
@app.route('/')
def foo():
return app.jinja_env.globals['foo']
c = app.test_client()
assert c.get('/').data == '42'
assert len(log) == 1
assert 'init_jinja_globals' in str(log[0]['message'])
def suite():
from minitwit_tests import MiniTwitTestCase
from flaskr_tests import FlaskrTestCase
@ -1576,6 +1595,7 @@ def suite():
suite.addTest(unittest.makeSuite(LoggingTestCase))
suite.addTest(unittest.makeSuite(ConfigTestCase))
suite.addTest(unittest.makeSuite(SubdomainTestCase))
suite.addTest(unittest.makeSuite(DeprecationsTestCase))
if flask.json_available:
suite.addTest(unittest.makeSuite(JSONTestCase))
if flask.signals_available:

Loading…
Cancel
Save