← Back to team overview

openerp-community-reviewer team mailing list archive

[Merge] lp:~camptocamp/lp-community-utils/nag-user-specific-info into lp:lp-community-utils

 

Yannick Vaucher @ Camptocamp has proposed merging lp:~camptocamp/lp-community-utils/nag-user-specific-info into lp:lp-community-utils.

Requested reviews:
  OpenERP Community Reviewer/Maintainer (openerp-community-reviewer)

For more details, see:
https://code.launchpad.net/~camptocamp/lp-community-utils/nag-user-specific-info/+merge/209665

Option --me to show what I'm supposed to do with that bunch of MPs
-- 
https://code.launchpad.net/~camptocamp/lp-community-utils/nag-user-specific-info/+merge/209665
Your team OpenERP Community Reviewer/Maintainer is requested to review the proposed merge of lp:~camptocamp/lp-community-utils/nag-user-specific-info into lp:lp-community-utils.
=== modified file 'openerp-nag'
--- openerp-nag	2014-02-20 16:18:06 +0000
+++ openerp-nag	2014-03-06 12:44:25 +0000
@@ -37,6 +37,7 @@
       period of time
     * Nagging about aging unanswered questions on launchpad answers
     * Nagging about accepted merge proposals that have not been merged yet
+    * Nagging by triaging MP in categories
 """
 
 from __future__ import unicode_literals, print_function
@@ -61,10 +62,20 @@
 # ...with the specified 'action'
 # ...about a particular 'subject'
 Nag = collections.namedtuple(
-    "Nag", "person action subject sort_class sort_priority sort_age project_name votes")
+    "Nag", "person action subject sort_class sort_priority sort_age project_name votes sort_user_categ")
 
 SORT_CLASS_BUG, SORT_CLASS_MERGE = range(2)
 
+MY_READY, MY_PENDING, REVIEWED_READY, REVIEWED_UPDATED, REVIEWED_PENDING, NOT_REVIEWED = range(6)
+
+USER_CATEGORIES = {
+        MY_READY: "My MPs ready to land",
+        MY_PENDING: "My MP needing some love",
+        REVIEWED_READY: "I'm ready to land, please Merge me !",
+        REVIEWED_UPDATED: "To check, updated since last need fixing vote",
+        REVIEWED_PENDING: "Nothing to do I've already reviewed it",
+        NOT_REVIEWED: "I didn't reviewed those ones",
+}
 
 def show_lp_object(obj):
     print(obj)
@@ -165,7 +176,7 @@
                     state, code in cls.__states__.iteritems())
 
 
-def gen_project_nags(lp, policy, project_name):
+def gen_project_nags(lp, policy, project_name, user_categ=False):
     # TODO: Detect project groups and redirect the nag to all projects
     # underneath that project
     # Access the project that we care about
@@ -173,11 +184,11 @@
     project = lp.projects[project_name]
     # Re-yield all the merge proposal nags
     # NOTE: change to yield from in py3k3
-    for nag in gen_merge_proposal_nags(lp, policy, project):
+    for nag in gen_merge_proposal_nags(lp, policy, project, user_categ):
         yield nag
 
 
-def gen_merge_proposal_nags(lp, policy, project):
+def gen_merge_proposal_nags(lp, policy, project, user_categ=False):
     # XXX: cannnot use utcnow as launchpad returns tz-aware objects here
     now = datetime.datetime.now(tz=UTC)
     logging.debug("Looking for merge proposals in project %r", project)
@@ -199,6 +210,7 @@
 
         # Nag about missing commit message on merge requests
         if policy.mps_need_commit_message and proposal.commit_message is None:
+
             yield Nag(
                 person=proposal.registrant.display_name,
                 action="set a commit message on merge request",
@@ -206,16 +218,29 @@
                 sort_class=SORT_CLASS_MERGE,
                 sort_priority=None,  # TODO: get from max(linked bugs)
                 sort_age=(proposal.date_review_requested - now).days,
+                sort_user_categ=None,
                 project_name=project.name,
                 votes=votes,
             )
 
         age = (now - proposal.date_review_requested).days
 
+        user_state = None
+        authenticated = lp.credential_store is not None
+        if user_categ:
+            me = lp.me
+            is_my_mp = proposal.registrant == me
         if (votes.approve == votes.total(for_approval=True) and
                 (votes.approve >= policy.approvals_to_bypass or
                  votes.approve >= policy.min_approve and
                  age >= policy.days_before_merge)):
+
+            if user_categ:
+                if is_my_mp:
+                    user_state = MY_READY
+                else:
+                    user_state = REVIEWED_READY
+
             yield Nag(
                 person='A committer',
                 action="consider to merge the proposal",
@@ -223,6 +248,7 @@
                 sort_class=SORT_CLASS_MERGE,
                 sort_priority=None,  # TODO: get from max(linked bugs)
                 sort_age=(proposal.date_review_requested - now).days,
+                sort_user_categ=user_state,
                 project_name=project.name,
                 votes=votes,
             )
@@ -230,6 +256,18 @@
 
         # Nag about aging merge requests
         if age >= policy.max_review_age:
+
+            if user_categ:
+                if is_my_mp:
+                    user_state = MY_PENDING
+                else:
+                    user_state = NOT_REVIEWED
+                    for v in proposal.votes:
+                        if v.reviewer == me:
+                            last_commit = proposal.source_branch.date_last_modified
+                            user_state = REVIEWED_UPDATED if v.date_created < last_commit and v.comment and v.comment.vote == 'Need Fixing' else REVIEWED_PENDING
+                            break
+
             yield Nag(
                 person='Someone',
                 action="review the merge request",
@@ -237,6 +275,7 @@
                 sort_class=SORT_CLASS_MERGE,
                 sort_priority=None,  # TODO: get from max(linked bugs)
                 sort_age=(proposal.date_review_requested - now).days,
+                sort_user_categ=user_state,
                 project_name=project.name,
                 votes=votes,
             )
@@ -296,6 +335,10 @@
     group.add_argument(
         '--production', action='store_const', const='production',
         dest='service_root', help="Use production launchpad instance")
+    group.add_argument(
+        '--user_categ', '--me', action='store_const', const='user_categ',
+        help="Use authenticated user to display MP in categories based on "
+             "their status")
     parser.set_defaults(anonymous=True, service_root='production')
     args = parser.parse_args()
     # Get the policy
@@ -303,6 +346,9 @@
     # Reconfigure logging
     if args.debug:
         logging.basicConfig(level=logging.DEBUG)
+    if args.user_categ:
+        args.authenticated = True
+        args.anonymous = False
     # Access Lauchpad object as the current (system) user or anonymously
     if args.anonymous:
         lp = Launchpad.login_anonymously(consumer_name, args.service_root)
@@ -329,23 +375,45 @@
         progress = ProgressBar(widgets=widgets, maxval=len(project_names)).start()
     for project_name in project_names:
         logging.info("Looking for things to nag about under %s", project_name)
-        nags.extend(gen_project_nags(lp, policy, project_name))
+        nags.extend(gen_project_nags(lp, policy, project_name, args.user_categ))
         if ProgressBar:
             progress.update(progress.currval + 1)
     if ProgressBar:
         progress.finish()
 
-    nags.sort(key=lambda nag: (nag.sort_class, nag.sort_priority,
-                               nag.sort_age))
+    #nags.sort(key=lambda nag: (nag.sort_class, nag.sort_priority,
+                               #nag.sort_age))
+    nags.sort(key=lambda nag: (nag.sort_user_categ, nag.sort_class,
+                               nag.sort_priority, nag.sort_age))
     print("=" * 80)
     print("Done thinking, here's the nag list".center(80))
     print("=" * 80)
-    for index1, nag in enumerate(nags, 1):
-        print("{index1:-2}: [age {age}] (votes {votes}) {person} should {action} {subject} "
-              "on the project {project}".format(
-                  index1=index1, age=(nag.sort_age and -nag.sort_age), person=nag.person,
-                  action=nag.action, subject=nag.subject, project=nag.project_name,
-                  votes=nag.votes or ''))
+
+
+    # Nag with user categories
+    if args.user_categ:
+        for sort_user_categ in range(6):
+            categ_nags = [nag for nag in enumerate(nags, 1)
+                          if nag[1].sort_user_categ == sort_user_categ]
+            if not categ_nags:
+                continue
+            print("=" * 80)
+            print(USER_CATEGORIES[sort_user_categ].center(80))
+            print("MP: %d".center(80) % len(categ_nags))
+            for index1, nag in categ_nags:
+                print("{index1:-2}: [age {age}] (votes {votes}) {person} should {action} {subject} "
+                      "on the project {project}".format(
+                          index1=index1, age=(nag.sort_age and -nag.sort_age), person=nag.person,
+                          action=nag.action, subject=nag.subject, project=nag.project_name,
+                          votes=nag.votes or ''))
+    else:
+        for index1, nag in enumerate(nags, 1):
+            print("{index1:-2}: [age {age}] (votes {votes}) {person} should {action} {subject} "
+                  "on the project {project}".format(
+                      index1=index1, age=(nag.sort_age and -nag.sort_age), person=nag.person,
+                      action=nag.action, subject=nag.subject, project=nag.project_name,
+                      votes=nag.votes or ''))
+
 
     print('Votes legend:')
     if args.anonymous:


Follow ups