Changeset - ba5fee3879c8
[Not reviewed]
default
0 4 0
Søren Løvborg - 10 years ago 2016-04-06 14:50:47
sorenl@unity3d.com
utils: improve extract_mentioned_users usefulness

Previously, extract_mentioned_users performed a regex search, converted
to a set to remove duplicates, converted that set back into a list, and
sorted the list on username, ignoring case. Every single caller of the
function then promptly took the carefully pruned and sorted result and
put it back into a set, rendering the entire exercise pointless.

In addition, every caller also resolved the usernames to database User
objects.

In this changeset, extract_mentioned_users is changed to return a set
of database User objects directly. A new extract_mentioned_usernames
function, which does only username extraction, is kept for the sole
purpose of providing a more testable interface (no database needed).

Bonus feature: The new extract_mentioned_users will prune non-existent
users, as well as the DEFAULT user. This means it is no longer possible
to @mention (and send notifications to) the DEFAULT user.
4 files changed with 23 insertions and 31 deletions:
0 comments (0 inline, 0 general)
kallithea/lib/utils2.py
Show inline comments
 
@@ -572,25 +572,30 @@ def time_to_datetime(tm):
 
                return
 
        return datetime.datetime.fromtimestamp(tm)
 

	
 

	
 
# Must match regexp in kallithea/public/js/base.js MentionsAutoComplete()
 
# Check char before @ - it must not look like we are in an email addresses.
 
# Matching is greedy so we don't have to look beyond the end.
 
MENTIONS_REGEX = re.compile(r'(?:^|(?<=[^a-zA-Z0-9]))@([a-zA-Z0-9][-_.a-zA-Z0-9]*[a-zA-Z0-9])')
 

	
 
def extract_mentioned_users(s):
 
def extract_mentioned_usernames(text):
 
    r"""
 
    Returns unique usernames from given string s that have @mention
 
    Returns list of (possible) usernames @mentioned in given text.
 

	
 
    :param s: string to get mentions
 

	
 
    >>> extract_mentioned_users('@1-2.a_X,@1234 not@not @ddd@not @n @ee @ff @gg, @gg;@hh @n\n@zz,')
 
    >>> extract_mentioned_usernames('@1-2.a_X,@1234 not@not @ddd@not @n @ee @ff @gg, @gg;@hh @n\n@zz,')
 
    ['1-2.a_X', '1234', 'ddd', 'ee', 'ff', 'gg', 'hh', 'zz']
 
    """
 
    usrs = set()
 
    for username in MENTIONS_REGEX.findall(s):
 
        usrs.add(username)
 
    return MENTIONS_REGEX.findall(text)
 

	
 
    return sorted(list(usrs), key=lambda k: k.lower())
 
def extract_mentioned_users(text):
 
    """ Returns set of actual database Users @mentioned in given text. """
 
    from kallithea.model.db import User
 
    result = set()
 
    for name in extract_mentioned_usernames(text):
 
        user = User.get_by_username(name, case_insensitive=True)
 
        if user is not None and user.username != User.DEFAULT_USER:
 
            result.add(user)
 
    return result
 

	
 

	
 
class AttributeDict(dict):
kallithea/model/comment.py
Show inline comments
 
@@ -51,14 +51,6 @@ class ChangesetCommentsModel(BaseModel):
 
    def __get_pull_request(self, pull_request):
 
        return self._get_instance(PullRequest, pull_request)
 

	
 
    def _extract_mentions(self, s):
 
        user_objects = []
 
        for username in extract_mentioned_users(s):
 
            user_obj = User.get_by_username(username, case_insensitive=True)
 
            if user_obj:
 
                user_objects.append(user_obj)
 
        return user_objects
 

	
 
    def _get_notification_data(self, repo, comment, user, comment_text,
 
                               line_no=None, revision=None, pull_request=None,
 
                               status_change=None, closing_pr=False):
 
@@ -210,8 +202,7 @@ class ChangesetCommentsModel(BaseModel):
 
                email_kwargs=email_kwargs,
 
            )
 

	
 
            mention_recipients = set(self._extract_mentions(body)) \
 
                                    .difference(recipients)
 
            mention_recipients = extract_mentioned_users(body).difference(recipients)
 
            if mention_recipients:
 
                email_kwargs['is_mention'] = True
 
                subj = _('[Mention]') + ' ' + subj
kallithea/model/pull_request.py
Show inline comments
 
@@ -35,7 +35,7 @@ from kallithea.lib import helpers as h
 
from kallithea.lib.exceptions import UserInvalidException
 
from kallithea.model import BaseModel
 
from kallithea.model.db import PullRequest, PullRequestReviewers, Notification, \
 
    ChangesetStatus, User
 
    ChangesetStatus
 
from kallithea.model.notification import NotificationModel
 
from kallithea.lib.utils2 import extract_mentioned_users, safe_unicode
 

	
 
@@ -109,8 +109,7 @@ class PullRequestModel(BaseModel):
 
            pull_request=new
 
        )
 

	
 
        mention_recipients = set(User.get_by_username(username, case_insensitive=True)
 
                                 for username in extract_mentioned_users(new.description))
 
        mention_recipients = extract_mentioned_users(new.description)
 
        self.__add_reviewers(created_by_user, new, reviewers, mention_recipients)
 

	
 
        return new
 
@@ -163,7 +162,6 @@ class PullRequestModel(BaseModel):
 
                                       email_kwargs=email_kwargs)
 

	
 
        if mention_recipients:
 
            mention_recipients.discard(None)
 
            mention_recipients.difference_update(reviewers)
 
        if mention_recipients:
 
            email_kwargs['is_mention'] = True
 
@@ -174,10 +172,8 @@ class PullRequestModel(BaseModel):
 
                                       email_kwargs=email_kwargs)
 

	
 
    def mention_from_description(self, user, pr, old_description=''):
 
        mention_recipients = set(User.get_by_username(username, case_insensitive=True)
 
                                 for username in extract_mentioned_users(pr.description))
 
        mention_recipients.difference_update(User.get_by_username(username, case_insensitive=True)
 
                                             for username in extract_mentioned_users(old_description))
 
        mention_recipients = (extract_mentioned_users(pr.description) -
 
                              extract_mentioned_users(old_description))
 

	
 
        log.debug("Mentioning %s", mention_recipients)
 
        self.__add_reviewers(user, pr, [], mention_recipients)
kallithea/tests/other/test_libs.py
Show inline comments
 
@@ -102,7 +102,7 @@ class TestLibs(BaseTestCase):
 
        self.assertEqual(str2bool(str_bool), expected)
 

	
 
    def test_mention_extractor(self):
 
        from kallithea.lib.utils2 import extract_mentioned_users
 
        from kallithea.lib.utils2 import extract_mentioned_usernames
 
        sample = (
 
            "@first hi there @world here's my email username@example.com "
 
            "@lukaszb check @one_more22 it pls @ ttwelve @D[] @one@two@three "
 
@@ -111,10 +111,10 @@ class TestLibs(BaseTestCase):
 
            "user.dot  hej ! not-needed maril@example.com"
 
        )
 

	
 
        s = sorted([
 
        expected = set([
 
            '2one_more22', 'first', 'lukaszb', 'one', 'one_more22', 'UPPER', 'cAmEL', 'john',
 
            'marian.user', 'marco-polo', 'marco_polo', 'world'], key=lambda k: k.lower())
 
        self.assertEqual(s, extract_mentioned_users(sample))
 
            'marian.user', 'marco-polo', 'marco_polo', 'world'])
 
        self.assertEqual(expected, set(extract_mentioned_usernames(sample)))
 

	
 
    @parameterized.expand([
 
        (dict(), u'just now'),
0 comments (0 inline, 0 general)