This is an automated email from the ASF dual-hosted git repository.
dill0wn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git
The following commit(s) were added to refs/heads/master by this push:
new 280bfe09d [#8497] rearrange ForgeMarkdown so it only instantiates a
full Markdown+extensions class when needed (cached_convert often does not need
it)
280bfe09d is described below
commit 280bfe09d7e27bf28bf13e95cdc077eb2ab6552b
Author: Dave Brondsema <[email protected]>
AuthorDate: Tue Feb 7 09:48:49 2023 -0500
[#8497] rearrange ForgeMarkdown so it only instantiates a full
Markdown+extensions class when needed (cached_convert often does not need it)
---
Allura/allura/lib/app_globals.py | 48 ++++++++++++++++++++++--------------
Allura/allura/tasks/mail_tasks.py | 6 ++---
Allura/allura/tests/test_globals.py | 6 ++---
Allura/allura/tests/test_markdown.py | 4 ++-
4 files changed, 38 insertions(+), 26 deletions(-)
diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py
index 05e1c1920..398d6bf3a 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -74,7 +74,26 @@ __all__ = ['Globals']
log = logging.getLogger(__name__)
-class ForgeMarkdown(markdown.Markdown):
+class ForgeMarkdown:
+
+ def __init__(self, **forge_ext_kwargs):
+ self.forge_ext_kwargs = forge_ext_kwargs
+
+ def make_markdown_instance(self, **forge_ext_kwargs):
+ # for further performance improvements, this might be cachable
including forge_ext_kwargs?
+ # but ForgeExtension and the classes it makes often save things on
`self` which might not be thread safe
+ # when multiple threads are using the same instance
+ # TestCachedMarkdown re-uses the same instance previously, and had a
bug that AddCustomClass wasn't running
+ return markdown.Markdown(
+ extensions=['markdown.extensions.fenced_code',
'markdown.extensions.codehilite',
+ 'markdown.extensions.abbr',
'markdown.extensions.def_list', 'markdown.extensions.footnotes',
+ 'markdown.extensions.md_in_html',
+ ForgeExtension(**forge_ext_kwargs),
+ EmojiExtension(),
+ UserMentionExtension(),
+ 'markdown.extensions.tables',
'markdown.extensions.toc', 'markdown.extensions.nl2br',
+ 'markdown_checklist.extension'],
+ output_format='html')
def convert(self, source, render_limit=True):
if render_limit and len(source) >
asint(config.get('markdown_render_max_length', 80000)):
@@ -84,7 +103,7 @@ class ForgeMarkdown(markdown.Markdown):
escaped = html.escape(h.really_unicode(source))
return Markup('<pre>%s</pre>' % escaped)
try:
- return super().convert(source)
+ return
self.make_markdown_instance(**self.forge_ext_kwargs).convert(source)
except Exception:
log.info('Invalid markdown: %s Upwards trace is %s', source,
''.join(traceback.format_stack()), exc_info=True)
@@ -460,29 +479,18 @@ class Globals:
else:
return Markup(pygments.highlight(text, lexer, formatter))
- def forge_markdown(self, **kwargs):
- '''return a markdown.Markdown object on which you can call convert'''
- return ForgeMarkdown(
- extensions=['markdown.extensions.fenced_code',
'markdown.extensions.codehilite',
- 'markdown.extensions.abbr',
'markdown.extensions.def_list', 'markdown.extensions.footnotes',
- 'markdown.extensions.md_in_html',
- ForgeExtension(**kwargs), EmojiExtension(),
UserMentionExtension(),
- 'markdown.extensions.tables',
'markdown.extensions.toc', 'markdown.extensions.nl2br',
- 'markdown_checklist.extension'],
- output_format='html')
-
@property
def markdown(self):
- return self.forge_markdown()
+ return ForgeMarkdown()
@property
def markdown_wiki(self):
if c.project and c.project.is_nbhd_project:
- return self.forge_markdown(wiki=True,
macro_context='neighborhood-wiki')
+ return ForgeMarkdown(wiki=True, macro_context='neighborhood-wiki')
elif c.project and c.project.is_user_project:
- return self.forge_markdown(wiki=True,
macro_context='userproject-wiki')
+ return ForgeMarkdown(wiki=True, macro_context='userproject-wiki')
else:
- return self.forge_markdown(wiki=True)
+ return ForgeMarkdown(wiki=True)
@property
def markdown_commit(self):
@@ -490,8 +498,10 @@ class Globals:
"""
app = getattr(c, 'app', None)
- return ForgeMarkdown(extensions=[CommitMessageExtension(app),
EmojiExtension(), 'markdown.extensions.nl2br'],
- output_format='html')
+ return markdown.Markdown(
+ extensions=[CommitMessageExtension(app), EmojiExtension(),
'markdown.extensions.nl2br'],
+ output_format='html',
+ )
@property
def production_mode(self):
diff --git a/Allura/allura/tasks/mail_tasks.py
b/Allura/allura/tasks/mail_tasks.py
index e2b2a0a15..8aae497c4 100644
--- a/Allura/allura/tasks/mail_tasks.py
+++ b/Allura/allura/tasks/mail_tasks.py
@@ -16,7 +16,6 @@
# under the License.
import html
import logging
-import six.moves.html_parser
import re
from tg import tmpl_context as c, app_globals as g, config
@@ -27,7 +26,7 @@ from allura.lib import helpers as h
from allura.lib.decorators import task
from allura.lib import mail_util
from allura.lib import exceptions as exc
-import six
+
log = logging.getLogger(__name__)
@@ -113,6 +112,7 @@ def create_multipart_msg(text, metalink=None):
:param metalink:
:return:
"""
+ from allura.lib.app_globals import ForgeMarkdown
def replace_html(matchobj):
text_within_div = matchobj.group(1)
@@ -129,7 +129,7 @@ def create_multipart_msg(text, metalink=None):
plain_text = html.unescape(plain_text) # put literal HTML tags back into
plaintext
plain_msg = mail_util.encode_email_part(plain_text, 'plain')
- html_text = g.forge_markdown(email=True).convert(text)
+ html_text = ForgeMarkdown(email=True).convert(text)
if metalink:
html_text = html_text + mail_meta_content(metalink)
html_msg = mail_util.encode_email_part(html_text, 'html')
diff --git a/Allura/allura/tests/test_globals.py
b/Allura/allura/tests/test_globals.py
index f02461bc4..1d26e0485 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -482,7 +482,7 @@ class Test():
</code></pre></div>
</div>''')
assert (
- g.forge_markdown(email=True).convert('[Home]') ==
+ ForgeMarkdown(email=True).convert('[Home]') ==
# uses localhost:
'<div class="markdown_content"><p><a class="alink"
href="http://localhost/p/test/wiki/Home/">[Home]</a></p></div>')
assert g.markdown.convert(dedent('''\
@@ -760,7 +760,7 @@ class TestCachedMarkdown(unittest.TestCase):
self.md = ForgeMarkdown()
self.post = M.Post()
self.post.text = '**bold**'
- self.expected_html = '<p><strong>bold</strong></p>'
+ self.expected_html = '<div
class="markdown_content"><p><strong>bold</strong></p></div>'
def test_bad_source_field_name(self):
self.assertRaises(AttributeError, self.md.cached_convert,
@@ -774,7 +774,7 @@ class TestCachedMarkdown(unittest.TestCase):
@patch.dict('allura.lib.app_globals.config',
markdown_cache_threshold='-0.01')
def test_non_ascii(self):
self.post.text = 'å∫ç'
- expected = '<p>å∫ç</p>'
+ expected = '<div class="markdown_content"><p>å∫ç</p></div>'
# test with empty cache
self.assertEqual(expected, self.md.cached_convert(self.post, 'text'))
# test with primed cache
diff --git a/Allura/allura/tests/test_markdown.py
b/Allura/allura/tests/test_markdown.py
index 992eec8b0..cd74a9c45 100644
--- a/Allura/allura/tests/test_markdown.py
+++ b/Allura/allura/tests/test_markdown.py
@@ -16,6 +16,8 @@
# under the License.
import unittest
+
+import markdown
import mock
from allura.lib import markdown_extensions as mde
@@ -140,7 +142,7 @@ Not *strong* or _underlined_."""
* <a href="/p/project/tool/2/tree/test.py#l3">source:test.py@2#L3</a></p>
<p>Not *strong* or _underlined_.</div>"""
- md = ForgeMarkdown(
+ md = markdown.Markdown(
extensions=[mde.CommitMessageExtension(app),
'markdown.extensions.nl2br'],
output_format='html')
self.assertEqual(md.convert(text), expected_html)