SF.net SVN: gar:[23437] csw/mgar/gar/v2/lib/python

wahwah at users.sourceforge.net wahwah at users.sourceforge.net
Sun Apr 20 16:32:29 CEST 2014


Revision: 23437
          http://sourceforge.net/p/gar/code/23437
Author:   wahwah
Date:     2014-04-20 14:32:28 +0000 (Sun, 20 Apr 2014)
Log Message:
-----------
Maintainer activity: incorporate mantis info

Mantis is the canonical source of maintainer status. This patch makes
the script download the mantis information and incorporate it in the
report.

Existing limitations:

- The script doesn't know who's old and who's new, it only looks whether
  there are any packages built by certain maintainer.
- The script doesn't look at the mailing lists, so some active people
  are marked as "to retire".

Modified Paths:
--------------
    csw/mgar/gar/v2/lib/python/activity.py
    csw/mgar/gar/v2/lib/python/maintainer_activity_report.py

Modified: csw/mgar/gar/v2/lib/python/activity.py
===================================================================
--- csw/mgar/gar/v2/lib/python/activity.py	2014-04-20 11:55:53 UTC (rev 23436)
+++ csw/mgar/gar/v2/lib/python/activity.py	2014-04-20 14:32:28 UTC (rev 23437)
@@ -10,7 +10,8 @@
 from lib.python import opencsw
 
 Maintainer = namedtuple('Maintainer',
-    ['username', 'pkgs', 'last_activity', 'last_activity_pkg', 'active'])
+    ['username', 'pkgs', 'last_activity', 'last_activity_pkg',
+     'active', 'mantis_status', 'fullname'])
 
 INACTIVE_MAINTAINER_CUTOFF = 2
 STALE_PACKAGE_CUTOFF = 4
@@ -98,7 +99,9 @@
         Maintainer(username=entry['maintainer'], pkgs={},
           last_activity=datetime.datetime(1970, 1, 1, 0, 0),
           last_activity_pkg=None,
-          active=True))
+          active=True,
+          mantis_status=None,
+          fullname=None))
     if entry['catalogname'] not in maintainer.pkgs:
       maintainer.pkgs[entry['catalogname']] = entry
     if maintainer.last_activity < date:

Modified: csw/mgar/gar/v2/lib/python/maintainer_activity_report.py
===================================================================
--- csw/mgar/gar/v2/lib/python/maintainer_activity_report.py	2014-04-20 11:55:53 UTC (rev 23436)
+++ csw/mgar/gar/v2/lib/python/maintainer_activity_report.py	2014-04-20 14:32:28 UTC (rev 23437)
@@ -44,26 +44,51 @@
       color: red;
       font-weight: bold;
     }
-    .can-be-retired-True {
-      background-color: #FED;
+    .retired-True {
+      background-color: #DDD;
+      color: #AAA;
     }
+    .action-needed-True {
+      background-color: #FA8;
+    }
   </style>
 </head>
 <body>
-  <h1>Maintainer activity report</h1>
+  <h1>OpenCSW Maintainer activity report</h1>
+  <h2>Maintainers to retire</h2>
+
+  <p>Limitations: This report doesn't know which maintainers are new and which ones are old.
+  New maintainers are reported as "to retire" until they release their first
+  package. The script only detects activity in the package catalogs. There are
+  people who are active in the project, even though they don't release
+  packages. They might be wrongly listed here as "to retire". Incorporating the
+  mailing list activity should help, but is not implemented right now.</p>
+
+  <p>The following list contains maintainers with no detected activity within
+  the last 2 years.</p>
+
   <p>
+  {% for username in analysis_by_username|sort %}
+  {% if analysis_by_username[username].to_retire %}
+    <a id="{{ username }}" class="maintainer"
+    href="http://www.opencsw.org/maintainers/{{ username }}/"
+    title="{{ maintainers[username].fullname }}">{{ username }}</a>
+  {% endif %}
+  {% endfor %}
   </p>
+  <h2>Activity</h2>
   <table>
   <tr>
     <th>username</th>
     <th>last activity</th>
     <th>years</th>
     <th>active?</th>
+    <th>mantis</th>
     <th>last pkg</th>
     <th># pkgs</th>
   </tr>
   {% for username in maintainers|sort %}
-    <tr class="active-{{ maintainers[username].active }} can-be-retired-{{ analysis_by_username[username].can_be_retired }}">
+    <tr class="active-{{ maintainers[username].active }} retired-{{ maintainers[username].mantis_status != 'Active' }} action-needed-{{ analysis_by_username[username].to_retire }}">
       <td>
         <a id="{{ username }}" class="maintainer"
         href="http://www.opencsw.org/maintainers/{{ username }}/">{{ username }}</a>
@@ -82,6 +107,9 @@
         {% endif %}
       </td>
       <td>
+        {{ maintainers[username].mantis_status }}
+      </td>
+      <td>
         <a href="http://buildfarm.opencsw.org/pkgdb/srv4/{{ maintainers[username].last_activity_pkg.md5_sum }}/">
         {{ maintainers[username].last_activity_pkg.catalogname }}</a>
       </td>
@@ -105,14 +133,20 @@
     return requests.get(url).json()
   results_by_catrel = {}
   with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
-    future_to_catrel = dict((executor.submit(Fetch, catrel), catrel)
-                            for catrel in catrels)
-    for future in concurrent.futures.as_completed(future_to_catrel):
-      catrel = future_to_catrel[future]
+    key_by_future = dict((executor.submit(Fetch, catrel), catrel)
+                         for catrel in catrels)
+
+    # Additional query: maintainers from Mantis
+    mantis_url = 'http://www.opencsw.org/buglist/maintainers'
+    mantis_future = executor.submit(lambda: requests.get(mantis_url).json())
+    key_by_future[mantis_future] = 'mantis'
+
+    for future in concurrent.futures.as_completed(key_by_future):
+      key = key_by_future[future]
       if future.exception() is not None:
         logging.warning('Fetching %r failed', url)
       else:
-        results_by_catrel[catrel] = future.result()
+        results_by_catrel[key] = future.result()
   return results_by_catrel
 
 
@@ -136,16 +170,51 @@
     with open(args.save_as, 'w') as fd:
       cPickle.dump(results_by_catrel, fd)
 
+  # We need to remove the mantis part.
+  mantis_maintainers = results_by_catrel['mantis']
+  del results_by_catrel['mantis']
+
+  # Flatten packages from all catalogs into a single list. For activity
+  # detection, we don't care which catalog a maintainer submitted a package to.
   pkgs = [item for sublist in results_by_catrel.values() for item in sublist]
+
+  # Shared code for activity detection. We're processing the unstable catalog
+  # separately, so we can detect whether each maintainer has any packages in
+  # the unstable catalog.
   maintainers, bad_dates = activity.Maintainers(pkgs)
   maintainers_in_unstable, _ = activity.Maintainers(results_by_catrel['unstable'])
 
+  for d in mantis_maintainers:
+    # maintainer, fullname, status
+    username = d['maintainer']
+    status = d['status']
+    if username in maintainers:
+      maintainers[username] = (
+          maintainers[username]._replace(mantis_status=status))
+    else:
+      maintainers[username] = (
+          activity.Maintainer(
+            username=username,
+            pkgs={},
+            last_activity=datetime.datetime(1970, 1, 1, 0, 0),
+            last_activity_pkg=None,
+            active=False,
+            mantis_status=status,
+            fullname=d['fullname']))
+
+  mantis_m_by_username = dict((m['maintainer'], m) for m in mantis_maintainers)
   analysis_by_username = {}
   for username, maintainer in maintainers.iteritems():
-    d = {'can_be_retired': False}
+    d = {'can_be_retired': False,
+         'to_retire': False,
+         'bogus': False}
+    if username not in mantis_m_by_username:
+      d['bogus'] = True
     if not maintainer.active:
       if username not in maintainers_in_unstable:
         d['can_be_retired'] = True
+      if maintainer.mantis_status != 'Retired' and not d['bogus']:
+        d['to_retire'] = True
     analysis_by_username[username] = d
 
   with open(args.output, 'w') as outfd:

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the devel mailing list