Trying to move my instance of wiki with existed database from 0.5 version to 0.7 I faced a problem when some of articles don't render. Poking around with article's content I found out that the certain sequence of markdown tags breaks down the web app causing internal server error (500).
Looking at logs and release notes I found out that there is a new plugin came out called "editsection
". Traceback of crashed app leads to the same plugin. Then I tried to reproduce an error turning on and off that plugin by editing INSTALLED_APPS
. That is how I came to this test scenario.
$ python --version
3.6.9
$ python ../bin/django-admin.py --version
3.1.5
$ uname -a
Linux laptop 5.4.0-58-generic #64~18.04.1-Ubuntu SMP Wed Dec 9 17:00:52 UTC 2020 i686 i686 i686 GNU/Linux
$ pip list
Package Version Location
appdirs 1.4.4
asgiref 3.3.1
attrs 20.3.0
beautifulsoup4 4.9.3
black 20.8b1
bleach 3.1.5
cfgv 3.2.0
click 7.1.2
coverage 5.3.1
cssselect 1.1.0
dataclasses 0.8
distlib 0.3.1
Django 3.1.5
django-classy-tags 2.0.0
django-functest 1.0.4
django-js-asset 1.2.2
django-mptt 0.11.0
django-nyt 1.1.6
django-sekizai 2.0.0
django-webtest 1.9.7
EasyProcess 0.3
entrypoints 0.3
filelock 3.0.12
flake8 3.7.9
furl 2.1.0
identify 1.5.11
importlib-metadata 3.3.0
importlib-resources 4.1.1
lxml 4.6.2
Markdown 3.2.2
mccabe 0.6.1
more-itertools 8.6.0
mypy-extensions 0.4.3
nodeenv 1.5.0
orderedmultidict 1.0.1
packaging 20.8
pathspec 0.8.1
Pillow 8.1.0
pip 20.3.3
pkg-resources 0.0.0
pluggy 0.13.1
pre-commit 2.9.3
py 1.10.0
pycodestyle 2.5.0
pyflakes 2.1.1
pyparsing 2.4.7
pyquery 1.4.3
pytest 5.3.5
pytest-cov 2.10.1
pytest-django 3.10.0
pytest-pythonpath 0.7.3
pytz 2020.5
PyVirtualDisplay 1.3.2
PyYAML 5.3.1
regex 2020.11.13
selenium 3.141.0
setuptools 51.1.1
six 1.15.0
sorl-thumbnail 12.7.0
soupsieve 2.1
sqlparse 0.4.1
toml 0.10.2
typed-ast 1.4.2
typing-extensions 3.7.4.3
urllib3 1.26.2
virtualenv 20.2.2
waitress 1.4.4
wcwidth 0.2.5
webencodings 0.5.1
WebOb 1.8.6
WebTest 2.0.35
wheel 0.36.2
wiki 0.7.2.dev20201229153254 /home/laptop/projects/django-wiki-0.7.1-dev/django-wiki/src
zipp 3.4.0
Yes, with 0.7.2dev branch
> An example of how to reproduce the bug.from django.conf import settings from django.shortcuts import resolve_url from ..base import ArticleWebTestUtils from ..base import DjangoClientTestBase from ..base import RequireRootArticleMixin from ..base import wiki_override_settings TEST_CONTENT = "### [Here we go](#anchor)" class CreateViewWithPluginTest( RequireRootArticleMixin, ArticleWebTestUtils, DjangoClientTestBase ): def test_create_article_with_plugin(self): response = self.client.post( resolve_url("wiki:create", path=""), {"title": "How to break Veiw by typo", "slug": "break", "content": TEST_CONTENT}, ) response = self.get_by_path("break/") self.assertLess(response.status_code, 500) class CreateViewWithoutPluginTest( RequireRootArticleMixin, ArticleWebTestUtils, DjangoClientTestBase ): def setUp(self): settings.INSTALLED_APPS = [ "django.contrib.humanize.apps.HumanizeConfig", "django.contrib.auth.apps.AuthConfig", "django.contrib.contenttypes.apps.ContentTypesConfig", "django.contrib.sessions.apps.SessionsConfig", "django.contrib.sites.apps.SitesConfig", "django.contrib.messages.apps.MessagesConfig", "django.contrib.staticfiles.apps.StaticFilesConfig", "django.contrib.admin.apps.AdminConfig", "django.contrib.admindocs.apps.AdminDocsConfig", "sekizai", "sorl.thumbnail", "django_nyt.apps.DjangoNytConfig", "wiki.apps.WikiConfig", "wiki.plugins.macros.apps.MacrosConfig", "wiki.plugins.help.apps.HelpConfig", "wiki.plugins.links.apps.LinksConfig", "wiki.plugins.images.apps.ImagesConfig", "wiki.plugins.attachments.apps.AttachmentsConfig", "wiki.plugins.notifications.apps.NotificationsConfig", #"wiki.plugins.editsection.apps.EditSectionConfig", "wiki.plugins.globalhistory.apps.GlobalHistoryConfig", "mptt", ] def test_create_article_without_plugin(self): response = self.client.post( resolve_url("wiki:create", path=""), {"title": "How to break Veiw by typo", "slug": "break2", "content": TEST_CONTENT}, ) response = self.get_by_path("break2/") self.assertLess(response.status_code, 500)> The expected result.
Do not return 5xx status code, if an engine cannot parse markup language or thinks that it is an incorrect markup language then it should displays user's input as is after sanitizing it, of course.
Error log================================================================= FAILURES ================================================================= ____________________________________________________ CreateViewTest.test_create_article ____________________________________________________ self = <tests.core.test_create_broken_article.CreateViewTest testMethod=test_create_article> def test_create_article(self): response = self.client.post( resolve_url("wiki:create", path=""), {"title": "How to break Veiw by typo", "slug": "break", "content": TEST_CONTENT}, ) > self.assertRedirects(response, resolve_url("wiki:get", path="break/")) tests/core/test_create_broken_article.py:19: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../lib/python3.6/site-packages/django/test/testcases.py:389: in assertRedirects **extra, ../lib/python3.6/site-packages/django/test/client.py:739: in get response = super().get(path, data=data, secure=secure, **extra) ../lib/python3.6/site-packages/django/test/client.py:395: in get **extra, ../lib/python3.6/site-packages/django/test/client.py:470: in generic return self.request(**r) ../lib/python3.6/site-packages/django/test/client.py:716: in request self.check_exception(response) ../lib/python3.6/site-packages/django/test/client.py:577: in check_exception raise exc_value ../lib/python3.6/site-packages/django/core/handlers/exception.py:47: in inner response = get_response(request) ../lib/python3.6/site-packages/django/core/handlers/base.py:204: in _get_response response = response.render() ../lib/python3.6/site-packages/django/template/response.py:105: in render self.content = self.rendered_content ../lib/python3.6/site-packages/django/template/response.py:83: in rendered_content return template.render(context, self._request) ../lib/python3.6/site-packages/django/template/backends/django.py:61: in render return self.template.render(context) ../lib/python3.6/site-packages/django/template/base.py:170: in render return self._render(context) ../lib/python3.6/site-packages/django/test/utils.py:96: in instrumented_test_render return self.nodelist.render(context) ../lib/python3.6/site-packages/django/template/base.py:938: in render bit = node.render_annotated(context) ../lib/python3.6/site-packages/django/template/base.py:905: in render_annotated return self.render(context) ../lib/python3.6/site-packages/django/template/loader_tags.py:150: in render return compiled_parent._render(context) ../lib/python3.6/site-packages/django/test/utils.py:96: in instrumented_test_render return self.nodelist.render(context) ../lib/python3.6/site-packages/django/template/base.py:938: in render bit = node.render_annotated(context) ../lib/python3.6/site-packages/django/template/base.py:905: in render_annotated return self.render(context) ../lib/python3.6/site-packages/django/template/loader_tags.py:150: in render return compiled_parent._render(context) ../lib/python3.6/site-packages/django/test/utils.py:96: in instrumented_test_render return self.nodelist.render(context) ../lib/python3.6/site-packages/django/template/base.py:938: in render bit = node.render_annotated(context) ../lib/python3.6/site-packages/django/template/base.py:905: in render_annotated return self.render(context) ../lib/python3.6/site-packages/django/template/loader_tags.py:150: in render return compiled_parent._render(context) ../lib/python3.6/site-packages/django/test/utils.py:96: in instrumented_test_render return self.nodelist.render(context) ../lib/python3.6/site-packages/django/template/base.py:938: in render bit = node.render_annotated(context) ../lib/python3.6/site-packages/django/template/base.py:905: in render_annotated return self.render(context) ../lib/python3.6/site-packages/classytags/core.py:151: in render return self.render_tag(context, **kwargs) ../lib/python3.6/site-packages/sekizai/templatetags/sekizai_tags.py:87: in render_tag rendered_contents = nodelist.render(context) ../lib/python3.6/site-packages/django/template/base.py:938: in render bit = node.render_annotated(context) ../lib/python3.6/site-packages/django/template/base.py:905: in render_annotated return self.render(context) ../lib/python3.6/site-packages/django/template/loader_tags.py:62: in render result = block.nodelist.render(context) ../lib/python3.6/site-packages/django/template/base.py:938: in render bit = node.render_annotated(context) ../lib/python3.6/site-packages/django/template/base.py:905: in render_annotated return self.render(context) ../lib/python3.6/site-packages/django/template/loader_tags.py:62: in render result = block.nodelist.render(context) ../lib/python3.6/site-packages/django/template/base.py:938: in render bit = node.render_annotated(context) ../lib/python3.6/site-packages/django/template/base.py:905: in render_annotated return self.render(context) ../lib/python3.6/site-packages/django/template/loader_tags.py:62: in render result = block.nodelist.render(context) ../lib/python3.6/site-packages/django/template/base.py:938: in render bit = node.render_annotated(context) ../lib/python3.6/site-packages/django/template/base.py:905: in render_annotated return self.render(context) ../lib/python3.6/site-packages/django/template/library.py:214: in render _dict = self.func(*resolved_args, **resolved_kwargs) src/wiki/templatetags/wiki_tags.py:53: in wiki_render content = article.get_cached_content(user=context.get("user")) src/wiki/models/article.py:261: in get_cached_content cached_content = self.render(user=user) src/wiki/models/article.py:219: in render content, self, preview=preview_content is not None, user=user src/wiki/core/markdown/__init__.py:53: in article_markdown return md.convert(text) src/wiki/core/markdown/__init__.py:31: in convert html = super().convert(text, *args, **kwargs) ../lib/python3.6/site-packages/markdown/core.py:267: in convert newRoot = treeprocessor.run(root) src/wiki/plugins/editsection/markdown_extensions.py:125: in run self.add_links(root) src/wiki/plugins/editsection/markdown_extensions.py:100: in add_links header_id = get_header_id(child.text) src/wiki/plugins/editsection/markdown_extensions.py:28: in get_header_id header_id = "".join(w[0] for w in re.findall(r"\w+", header)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ pattern = '\\w+', string = None, flags = 0 def findall(pattern, string, flags=0): """Return a list of all non-overlapping matches in the string. If one or more capturing groups are present in the pattern, return a list of groups; this will be a list of tuples if the pattern has more than one group. Empty matches are included in the result.""" > return _compile(pattern, flags).findall(string) E TypeError: expected string or bytes-like object ../lib/python3.6/re.py:222: TypeError ------------------------------------------------------------ Captured log call ------------------------------------------------------------- ERROR django.request:log.py:230 Internal Server Error: /break/ Traceback (most recent call last): File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/core/handlers/exception.py", line 47, in inner response = get_response(request) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/core/handlers/base.py", line 204, in _get_response response = response.render() File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/response.py", line 105, in render self.content = self.rendered_content File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/response.py", line 83, in rendered_content return template.render(context, self._request) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/backends/django.py", line 61, in render return self.template.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 170, in render return self._render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/test/utils.py", line 96, in instrumented_test_render return self.nodelist.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/loader_tags.py", line 150, in render return compiled_parent._render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/test/utils.py", line 96, in instrumented_test_render return self.nodelist.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/loader_tags.py", line 150, in render return compiled_parent._render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/test/utils.py", line 96, in instrumented_test_render return self.nodelist.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/loader_tags.py", line 150, in render return compiled_parent._render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/test/utils.py", line 96, in instrumented_test_render return self.nodelist.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/classytags/core.py", line 151, in render return self.render_tag(context, **kwargs) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/sekizai/templatetags/sekizai_tags.py", line 87, in render_tag rendered_contents = nodelist.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/loader_tags.py", line 62, in render result = block.nodelist.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/loader_tags.py", line 62, in render result = block.nodelist.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/loader_tags.py", line 62, in render result = block.nodelist.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/django/template/library.py", line 214, in render _dict = self.func(*resolved_args, **resolved_kwargs) File "/home/laptop/projects/django-wiki-0.7.1-dev/django-wiki/src/wiki/templatetags/wiki_tags.py", line 53, in wiki_render content = article.get_cached_content(user=context.get("user")) File "/home/laptop/projects/django-wiki-0.7.1-dev/django-wiki/src/wiki/models/article.py", line 261, in get_cached_content cached_content = self.render(user=user) File "/home/laptop/projects/django-wiki-0.7.1-dev/django-wiki/src/wiki/models/article.py", line 219, in render content, self, preview=preview_content is not None, user=user File "/home/laptop/projects/django-wiki-0.7.1-dev/django-wiki/src/wiki/core/markdown/__init__.py", line 53, in article_markdown return md.convert(text) File "/home/laptop/projects/django-wiki-0.7.1-dev/django-wiki/src/wiki/core/markdown/__init__.py", line 31, in convert html = super().convert(text, *args, **kwargs) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/site-packages/markdown/core.py", line 267, in convert newRoot = treeprocessor.run(root) File "/home/laptop/projects/django-wiki-0.7.1-dev/django-wiki/src/wiki/plugins/editsection/markdown_extensions.py", line 125, in run self.add_links(root) File "/home/laptop/projects/django-wiki-0.7.1-dev/django-wiki/src/wiki/plugins/editsection/markdown_extensions.py", line 100, in add_links header_id = get_header_id(child.text) File "/home/laptop/projects/django-wiki-0.7.1-dev/django-wiki/src/wiki/plugins/editsection/markdown_extensions.py", line 28, in get_header_id header_id = "".join(w[0] for w in re.findall(r"\w+", header)) File "/home/laptop/projects/django-wiki-0.7.1-dev/lib/python3.6/re.py", line 222, in findall return _compile(pattern, flags).findall(string) TypeError: expected string or bytes-like object
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4