Skip to content

Commit b9dd430

Browse files
Correct template rendering
No longer modify the Jinja environment globals with each request processing. Doing otherwise caused issues with objects not being released as expected (e.g. "clock") because they were still being referenced somewhere in cached content created by the rendering engine. > Environment globals should not be changed after loading any templates, and template globals should not be changed at any time after loading the template. Changing globals after loading a template will result in unexpected behavior as they may be shared between the environment and other templates. See <https://jinja.palletsprojects.com/en/stable/api/#the-global-namespace> A context procesor is used instead to inject common variables to the rendering engine. Template import statements must specify "with context" when accessing context variables like e.g. "gen".
1 parent b72b4f5 commit b9dd430

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+108
-101
lines changed

src/moin/app.py

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@
2929
from jinja2 import ChoiceLoader, FileSystemLoader
3030
from whoosh.index import EmptyIndexError
3131

32-
from moin.utils import monkeypatch # noqa
33-
from moin.utils.clock import Clock
3432
from moin import auth, user, config
3533
from moin.constants.misc import ANON
3634
from moin.i18n import i18n_init
37-
from moin.themes import setup_jinja_env, themed_error
35+
from moin.search import SearchForm
3836
from moin.storage.middleware import protecting, indexing, routing
37+
from moin.themes import setup_jinja_env, themed_error, ThemeSupport
38+
from moin.utils import monkeypatch # noqa
39+
from moin.utils.clock import Clock
40+
from moin.utils.forms import make_generator
3941
from moin.wikiutil import WikiLinkAnalyzer
4042

4143
from moin import log
@@ -192,7 +194,9 @@ class ItemNameConverter(PathConverter):
192194
if app.cfg.template_dirs:
193195
app.jinja_env.loader = ChoiceLoader([FileSystemLoader(app.cfg.template_dirs), app.jinja_env.loader])
194196
app.register_error_handler(403, themed_error)
197+
app.context_processor(inject_common_template_vars)
195198
app.cfg.custom_css_path = os.path.isfile("wiki_local/custom.css")
199+
setup_jinja_env(app.jinja_env)
196200
clock.stop("create_app flask-theme")
197201
# Create a global counter to limit Content Security Policy reports and prevent spam
198202
app.csp_count = 0
@@ -313,18 +317,37 @@ def setup_user_anon():
313317
flaskg.user = user.User(name=ANON, auth_method="invalid")
314318

315319

320+
def inject_common_template_vars() -> dict[str, Any]:
321+
if getattr(flaskg, "no_variable_injection", False):
322+
return {}
323+
else:
324+
return {
325+
"clock": flaskg.clock,
326+
"storage": flaskg.storage,
327+
"user": flaskg.user,
328+
"item_name": request.view_args.get("item_name", ""),
329+
"theme_supp": ThemeSupport(app.cfg),
330+
"cfg": app.cfg,
331+
"gen": make_generator(),
332+
"search_form": SearchForm.from_defaults(),
333+
}
334+
335+
316336
def before_wiki():
317337
"""
318338
Setup environment for wiki requests, start timers.
319339
"""
320-
if request and (is_static_content(request.path) or request.path == "/+cspreport/log"):
321-
logging.debug(f"skipping before_wiki for {request.path}")
340+
request_path = getattr(request, "path", "") if request else ""
341+
if is_static_content(request_path) or request_path == "/+cspreport/log":
342+
logging.debug(f"skipping variable injection in before_wiki for {request.path}")
343+
setattr(flaskg, "no_variable_injection", True)
322344
return
323345

324346
logging.debug("running before_wiki")
325-
flaskg.clock = Clock()
326-
flaskg.clock.start("total")
327-
flaskg.clock.start("init")
347+
348+
clock = flaskg.clock = Clock()
349+
clock.start("total")
350+
clock.start("init")
328351
try:
329352
flaskg.unprotected_storage = app.storage
330353
cli_no_request_ctx = False
@@ -342,40 +365,32 @@ def before_wiki():
342365
if cli_no_request_ctx: # no request.user_agent if this is pytest or cli
343366
flaskg.add_lineno_attr = False
344367
else:
345-
setup_jinja_env()
346368
flaskg.add_lineno_attr = request.headers.get("User-Agent", None) and flaskg.user.edit_on_doubleclick
347369
finally:
348-
flaskg.clock.stop("init")
370+
clock.stop("init")
349371

350372

351373
def teardown_wiki(response):
352374
"""
353375
Teardown environment of wiki requests, stop timers.
354376
"""
355-
if request:
356-
request_path = request.path
357-
if is_static_content(request_path):
358-
return response
359-
else:
360-
request_path = ""
377+
request_path = getattr(request, "path", "")
378+
if is_static_content(request_path) or request_path == "/+cspreport/log":
379+
return response
361380

362381
logging.debug("running teardown_wiki")
363382

364-
if hasattr(flaskg, "edit_utils"):
383+
if edit_utils := getattr(flaskg, "edit_utils", None):
365384
# if transaction fails with sql file locked, we try to free it here
366385
try:
367-
flaskg.edit_utils.conn.close()
386+
edit_utils.conn.close()
368387
except AttributeError:
369388
pass
370389

371390
try:
372391
# whoosh cache performance
373-
for cache in (
374-
flaskg.storage.parse_acl,
375-
flaskg.storage.eval_acl,
376-
flaskg.storage.get_acls,
377-
flaskg.storage.allows,
378-
):
392+
storage = flaskg.storage
393+
for cache in (storage.parse_acl, storage.eval_acl, storage.get_acls, storage.allows):
379394
if cache.cache_info()[3] > 0:
380395
msg = "cache = %s: hits = %s, misses = %s, maxsize = %s, size = %s" % (
381396
(cache.__name__,) + cache.cache_info()
@@ -386,8 +401,10 @@ def teardown_wiki(response):
386401
pass
387402

388403
try:
389-
flaskg.clock.stop("total", comment=request_path)
390-
del flaskg.clock
404+
clock = flaskg.pop("clock", None)
405+
if clock is not None:
406+
clock.stop("total", comment=request_path)
407+
del clock
391408
except AttributeError:
392409
# can happen if teardown_wiki() is called twice, e.g. by unit tests.
393410
pass

src/moin/apps/admin/templates/admin/group_acl_report.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#}
1212

1313
{% extends theme("layout.html") %}
14-
{% import "utils.html" as utils %}
14+
{% import "utils.html" as utils with context %}
1515
{% block content %}
1616
<h1>{{ _("Group ACL Report") }}</h1>
1717
<h2>{{ _("Group Name") }}: {{ group_name }}</h2>

src/moin/apps/admin/templates/admin/groupbrowser.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{% extends theme("layout.html") %}
2-
{% import "utils.html" as utils %}
2+
{% import "utils.html" as utils with context %}
33
{% block content %}
44
<h1>{{ _("Groups") }}</h1>
55
<table id="moin-group-browser" class="zebra moin-sortable" data-sortlist="[[0,0]]">

src/moin/apps/admin/templates/admin/register_new_user.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#}
55

66
{% extends theme("layout.html") %}
7-
{% import "forms.html" as forms %}
7+
{% import "forms.html" as forms with context %}
88

99
{% block content %}
1010
<h1>{{ _("Register New User") }}</h1>

src/moin/apps/admin/templates/admin/trash.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{% extends theme("layout.html") %}
2-
{% import "utils.html" as utils %}
2+
{% import "utils.html" as utils with context %}
33
{% block content %}
44
{% if headline %}
55
<h1>{{ headline }}</h1>

src/moin/apps/admin/templates/admin/user_acl_report.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#}
1212

1313
{% extends theme("layout.html") %}
14-
{% import "utils.html" as utils %}
14+
{% import "utils.html" as utils with context %}
1515
{% block content %}
1616
<h1>{{ _("User ACL Report") }}</h1>
1717
<h2>{{ _("User Names") }}: {{ user_names|join(', ') }}</h2>

src/moin/apps/admin/templates/user/highlighterhelp.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{% import "utils.html" as utils %}
1+
{% import "utils.html" as utils with context %}
22
{% extends theme("layout.html") %}
33
{% block content %}
44
<h1>{{ _("Highlighters") }}</h1>

src/moin/apps/admin/templates/user/interwikihelp.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{% import "utils.html" as utils %}
1+
{% import "utils.html" as utils with context %}
22
{% extends theme("layout.html") %}
33
{% block content %}
44
<h1>{{ _("InterWiki Names") }}</h1>

src/moin/apps/admin/templates/user/itemsize.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{% import "utils.html" as utils %}
1+
{% import "utils.html" as utils with context %}
22
{% extends theme("layout.html") %}
33
{% block content %}
44
<h1>{{ _("Item Sizes (last revision)") }}</h1>

src/moin/templates/404.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
abort(404, item_name) # where item_name is the local item name
66
#}
77

8-
{% import "forms.html" as forms %}
8+
{% import "forms.html" as forms with context %}
99
{% extends theme("layout.html") %}
1010

1111
{% block content %}

0 commit comments

Comments
 (0)