This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8497
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 242ce6427c593854921aa5f536b514ae0f6f9c93
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 7fe9ffb16..8a004d6b0 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 b0e4d56af..9b7497890 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)

Reply via email to