bugdown: Store if message has wildcards in MentionData.

We also switch the underlying exctact_mention_text method to use
a regular for loop, as well as make the related methods return
tuples of (names, is_wildcard). This abstraction is hidden from the
MentionData callers behind mention_data.message_has_wildcards().

Concerns #13430.
This commit is contained in:
Rohitt Vashishtha 2019-11-22 09:38:34 +00:00 committed by Tim Abbott
parent fb9e2b68fd
commit 9174c636ce
3 changed files with 28 additions and 15 deletions

View File

@ -2114,7 +2114,7 @@ def get_possible_mentions_info(realm_id: int, mention_texts: Set[str]) -> List[F
class MentionData: class MentionData:
def __init__(self, realm_id: int, content: str) -> None: def __init__(self, realm_id: int, content: str) -> None:
mention_texts = possible_mentions(content) mention_texts, has_wildcards = possible_mentions(content)
possible_mentions_info = get_possible_mentions_info(realm_id, mention_texts) possible_mentions_info = get_possible_mentions_info(realm_id, mention_texts)
self.full_name_info = { self.full_name_info = {
row['full_name'].lower(): row row['full_name'].lower(): row
@ -2125,6 +2125,10 @@ class MentionData:
for row in possible_mentions_info for row in possible_mentions_info
} }
self.init_user_group_data(realm_id=realm_id, content=content) self.init_user_group_data(realm_id=realm_id, content=content)
self.has_wildcards = has_wildcards
def message_has_wildcards(self) -> bool:
return self.has_wildcards
def init_user_group_data(self, def init_user_group_data(self,
realm_id: int, realm_id: int,

View File

@ -12,25 +12,29 @@ wildcards = ['all', 'everyone', 'stream']
def user_mention_matches_wildcard(mention: str) -> bool: def user_mention_matches_wildcard(mention: str) -> bool:
return mention in wildcards return mention in wildcards
def extract_mention_text(m: Tuple[str, str]) -> Optional[str]: def extract_mention_text(m: Tuple[str, str]) -> Tuple[Optional[str], bool]:
# re.findall provides tuples of match elements; we want the second # re.findall provides tuples of match elements; we want the second
# to get the main mention content. # to get the main mention content.
s = m[1] s = m[1]
if s.startswith("**") and s.endswith("**"): if s.startswith("**") and s.endswith("**"):
text = s[2:-2] text = s[2:-2]
if text in wildcards: if text in wildcards:
return None return None, True
return text return text, False
return None, False
# We don't care about @all, @everyone or @stream def possible_mentions(content: str) -> Tuple[Set[str], bool]:
return None
def possible_mentions(content: str) -> Set[str]:
matches = re.findall(find_mentions, content) matches = re.findall(find_mentions, content)
# mention texts can either be names, or an extended name|id syntax. # mention texts can either be names, or an extended name|id syntax.
texts_with_none = (extract_mention_text(match) for match in matches) texts = set()
texts = {text for text in texts_with_none if text} message_has_wildcards = False
return texts for match in matches:
text, is_wildcard = extract_mention_text(match)
if text:
texts.add(text)
if is_wildcard:
message_has_wildcards = True
return texts, message_has_wildcards
def extract_user_group(matched_text: str) -> str: def extract_user_group(matched_text: str) -> str:
return matched_text[1:-1] return matched_text[1:-1]

View File

@ -242,6 +242,11 @@ class BugdownMiscTest(ZulipTestCase):
assert(user is not None) assert(user is not None)
self.assertEqual(user['email'], hamlet.email) self.assertEqual(user['email'], hamlet.email)
self.assertFalse(mention_data.message_has_wildcards())
content = '@**King Hamlet** @**Cordelia lear** @**all**'
mention_data = bugdown.MentionData(realm.id, content)
self.assertTrue(mention_data.message_has_wildcards())
def test_invalid_katex_path(self) -> None: def test_invalid_katex_path(self) -> None:
with self.settings(DEPLOY_ROOT="/nonexistent"): with self.settings(DEPLOY_ROOT="/nonexistent"):
with mock.patch('logging.error') as mock_logger: with mock.patch('logging.error') as mock_logger:
@ -1344,17 +1349,17 @@ class BugdownTest(ZulipTestCase):
self.assertEqual(msg.mentions_user_ids, set()) self.assertEqual(msg.mentions_user_ids, set())
def test_possible_mentions(self) -> None: def test_possible_mentions(self) -> None:
def assert_mentions(content: str, names: Set[str]) -> None: def assert_mentions(content: str, names: Set[str], has_wildcards: Optional[bool]=False) -> None:
self.assertEqual(possible_mentions(content), names) self.assertEqual(possible_mentions(content), (names, has_wildcards))
assert_mentions('', set()) assert_mentions('', set())
assert_mentions('boring', set()) assert_mentions('boring', set())
assert_mentions('@**all**', set()) assert_mentions('@**all**', set(), True)
assert_mentions('smush@**steve**smush', set()) assert_mentions('smush@**steve**smush', set())
assert_mentions( assert_mentions(
'Hello @**King Hamlet** and @**Cordelia Lear**\n@**Foo van Barson|1234** @**all**', 'Hello @**King Hamlet** and @**Cordelia Lear**\n@**Foo van Barson|1234** @**all**',
{'King Hamlet', 'Cordelia Lear', 'Foo van Barson|1234'} {'King Hamlet', 'Cordelia Lear', 'Foo van Barson|1234'}, True
) )
def test_mention_multiple(self) -> None: def test_mention_multiple(self) -> None: