comments: allow parsing the issue tracker patterns inside the markup

language for comments.

- need to pass in repo name to renderer helper to activate it.
This commit is contained in:
Marcin Kuzminski 2017-04-20 16:26:15 +02:00
parent d3bd2c6229
commit ecea35f018
2 changed files with 77 additions and 44 deletions

View file

@ -1602,16 +1602,24 @@ def urlify_commits(text_, repository):
def _process_url_func(match_obj, repo_name, uid, entry,
return_raw_data=False):
return_raw_data=False, link_format='html'):
pref = ''
if match_obj.group().startswith(' '):
pref = ' '
issue_id = ''.join(match_obj.groups())
tmpl = (
'%(pref)s<a class="%(cls)s" href="%(url)s">'
'%(issue-prefix)s%(id-repr)s'
'</a>')
if link_format == 'html':
tmpl = (
'%(pref)s<a class="%(cls)s" href="%(url)s">'
'%(issue-prefix)s%(id-repr)s'
'</a>')
elif link_format == 'rst':
tmpl = '`%(issue-prefix)s%(id-repr)s <%(url)s>`_'
elif link_format == 'markdown':
tmpl = '[%(issue-prefix)s%(id-repr)s](%(url)s)'
else:
raise ValueError('Bad link_format:{}'.format(link_format))
(repo_name_cleaned,
parent_group_name) = RepoGroupModel().\
@ -1644,7 +1652,12 @@ def _process_url_func(match_obj, repo_name, uid, entry,
return tmpl % data
def process_patterns(text_string, repo_name, config=None):
def process_patterns(text_string, repo_name, link_format='html'):
allowed_formats = ['html', 'rst', 'markdown']
if link_format not in allowed_formats:
raise ValueError('Link format can be only one of:{} got {}'.format(
allowed_formats, link_format))
repo = None
if repo_name:
# Retrieving repo_name to avoid invalid repo_name to explode on
@ -1656,6 +1669,7 @@ def process_patterns(text_string, repo_name, config=None):
issues_data = []
newtext = text_string
for uid, entry in active_entries.items():
log.debug('found issue tracker entry with uid %s' % (uid,))
@ -1682,7 +1696,8 @@ def process_patterns(text_string, repo_name, config=None):
issues_data.append(data_func(match_obj))
url_func = partial(
_process_url_func, repo_name=repo_name, entry=entry, uid=uid)
_process_url_func, repo_name=repo_name, entry=entry, uid=uid,
link_format=link_format)
newtext = pattern.sub(url_func, newtext)
log.debug('processed prefix:uid `%s`' % (uid,))
@ -1750,7 +1765,8 @@ def renderer_from_filename(filename, exclude=None):
return None
def render(source, renderer='rst', mentions=False, relative_url=None):
def render(source, renderer='rst', mentions=False, relative_url=None,
repo_name=None):
def maybe_convert_relative_links(html_source):
if relative_url:
@ -1758,11 +1774,21 @@ def render(source, renderer='rst', mentions=False, relative_url=None):
return html_source
if renderer == 'rst':
if repo_name:
# process patterns on comments if we pass in repo name
source, issues = process_patterns(
source, repo_name, link_format='rst')
return literal(
'<div class="rst-block">%s</div>' %
maybe_convert_relative_links(
MarkupRenderer.rst(source, mentions=mentions)))
elif renderer == 'markdown':
if repo_name:
# process patterns on comments if we pass in repo name
source, issues = process_patterns(
source, repo_name, link_format='markdown')
return literal(
'<div class="markdown-block">%s</div>' %
maybe_convert_relative_links(

View file

@ -103,55 +103,62 @@ def test_extract_issues(backend, text_string, pattern, expected):
assert issues == expected
@pytest.mark.parametrize('text_string, pattern, expected_text', [
('Fix #42', '(?:#)(?P<issue_id>\d+)',
'Fix <a class="issue-tracker-link" href="http://r.io/{repo}/i/42">#42</a>'
),
('Fix #42', '(?:#)?<issue_id>\d+)', 'Fix #42'), # Broken regex
@pytest.mark.parametrize('text_string, pattern, link_format, expected_text', [
('Fix #42', '(?:#)(?P<issue_id>\d+)', 'html',
'Fix <a class="issue-tracker-link" href="http://r.io/{repo}/i/42">#42</a>'),
('Fix #42', '(?:#)(?P<issue_id>\d+)', 'markdown',
'Fix [#42](http://r.io/{repo}/i/42)'),
('Fix #42', '(?:#)(?P<issue_id>\d+)', 'rst',
'Fix `#42 <http://r.io/{repo}/i/42>`_'),
('Fix #42', '(?:#)?<issue_id>\d+)', 'html',
'Fix #42'), # Broken regex
])
def test_process_patterns_repo(backend, text_string, pattern, expected_text):
def test_process_patterns_repo(backend, text_string, pattern, expected_text, link_format):
repo = backend.create_repo()
config = {'123': {
'uid': '123',
'pat': pattern,
'url': 'http://r.io/${repo}/i/${issue_id}',
'pref': '#',
}
}
def get_settings_mock(self, cache=True):
return config
return {
'123': {
'uid': '123',
'pat': pattern,
'url': 'http://r.io/${repo}/i/${issue_id}',
'pref': '#',
}
}
with mock.patch.object(IssueTrackerSettingsModel,
'get_settings', get_settings_mock):
processed_text, issues = helpers.process_patterns(
text_string, repo.repo_name, config)
text_string, repo.repo_name, link_format)
assert processed_text == expected_text.format(repo=repo.repo_name)
@pytest.mark.parametrize('text_string, pattern, expected_text', [
('Fix #42', '(?:#)(?P<issue_id>\d+)',
'Fix <a class="issue-tracker-link" href="http://r.io/i/42">#42</a>'
),
('Fix #42', '(?:#)?<issue_id>\d+)', 'Fix #42'), # Broken regex
'Fix <a class="issue-tracker-link" href="http://r.io/i/42">#42</a>'),
('Fix #42', '(?:#)?<issue_id>\d+)',
'Fix #42'), # Broken regex
])
def test_process_patterns_no_repo(text_string, pattern, expected_text):
config = {'123': {
'uid': '123',
'pat': pattern,
'url': 'http://r.io/i/${issue_id}',
'pref': '#',
}
}
def get_settings_mock(self, cache=True):
return config
return {
'123': {
'uid': '123',
'pat': pattern,
'url': 'http://r.io/i/${issue_id}',
'pref': '#',
}
}
with mock.patch.object(IssueTrackerSettingsModel,
'get_global_settings', get_settings_mock):
processed_text, issues = helpers.process_patterns(
text_string, '', config)
text_string, '')
assert processed_text == expected_text
@ -161,21 +168,21 @@ def test_process_patterns_non_existent_repo_name(backend):
pattern = '(?:#)(?P<issue_id>\d+)'
expected_text = ('Fix <a class="issue-tracker-link" '
'href="http://r.io/do-not-exist/i/42">#42</a>')
config = {'123': {
'uid': '123',
'pat': pattern,
'url': 'http://r.io/${repo}/i/${issue_id}',
'pref': '#',
}
}
def get_settings_mock(self, cache=True):
return config
return {
'123': {
'uid': '123',
'pat': pattern,
'url': 'http://r.io/${repo}/i/${issue_id}',
'pref': '#',
}
}
with mock.patch.object(IssueTrackerSettingsModel,
'get_global_settings', get_settings_mock):
processed_text, issues = helpers.process_patterns(
text_string, 'do-not-exist', config)
text_string, 'do-not-exist')
assert processed_text == expected_text