[damned-lies] Add support for more than one coordinator per team



commit 8ba2f1f2e4ee810cb3af44d537fd1c576c65db1b
Author: Claude Paroz <claude 2xlibre net>
Date:   Fri Jan 18 18:22:52 2013 +0100

    Add support for more than one coordinator per team

 teams/models.py                |   66 ++++++++++++++++-----------------------
 teams/tests.py                 |   42 ++++++++-----------------
 teams/views.py                 |    2 -
 templates/teams/team_base.html |    8 ++---
 templates/teams/team_list.html |    8 ++---
 templates/teams/team_list.xml  |    8 ++---
 6 files changed, 50 insertions(+), 84 deletions(-)
---
diff --git a/teams/models.py b/teams/models.py
index 6872a12..9569dae 100644
--- a/teams/models.py
+++ b/teams/models.py
@@ -39,18 +39,15 @@ class TeamManager(models.Manager):
         roles.
         """
         teams = self.all()
-        roles = Role.objects.select_related("person").filter(role='coordinator',
-                                                                is_active=True)
+        roles = Role.objects.select_related("person").filter(role='coordinator')
         role_dict = {}
 
         for role in roles:
-            # Only one coordinator by team
-            role_dict[role.team_id] = role
+            role_dict.setdefault(role.team_id, []).append(role.person)
 
         for team in teams:
             try:
-                role = role_dict[team.id]
-                team.roles = {'coordinator': [role.person]}
+                team.roles = {'coordinator': role_dict[team.id]}
             except KeyError:
                 # Abnormal because a team must have a coordinator but of no
                 # consequence
@@ -102,7 +99,7 @@ class Team(models.Model):
 
     def __init__(self, *args, **kwargs):
         models.Model.__init__(self, *args, **kwargs)
-        self.roles = None
+        self.roles = {}
 
     def __unicode__(self):
         return self.description
@@ -115,8 +112,8 @@ class Team(models.Model):
         """ Return True if user is allowed to edit this team
             user is a User (from request.user), not a Person
         """
-        coordinator = self.get_coordinator()
-        return user.is_authenticated() and coordinator and user.username == coordinator.username
+        return (user.is_authenticated() and
+                user.username in [p.username for p in self.get_coordinators()])
 
     def fill_role(self, role, person):
         """ Used by TeamManager to prefill roles in team """
@@ -133,27 +130,18 @@ class Team(models.Model):
     def get_languages(self):
         return self.language_set.all()
 
-    def get_coordinator(self):
-        try:
-            return self.roles['coordinator'][0]
-        except:
-            try:
-                # The join by role__team__id generates only one query and
-                # the same one by role__team=self two queries!
-                return Person.objects.get(role__team__id=self.id,
-                                          role__role='coordinator')
-            except Person.DoesNotExist:
-                return None
-
-    def get_members_by_role_exact(self, role):
+    def get_members_by_role_exact(self, role, only_active=True):
         """ Return a list of active members """
         try:
             return self.roles[role]
-        except:
-            members = list(Person.objects.filter(role__team__id=self.id,
-                                                 role__role=role,
-                                                 role__is_active=True))
-            return members
+        except KeyError:
+            members = Person.objects.filter(role__team__id=self.id, role__role=role)
+            if only_active:
+                members = members.filter(role__is_active=True)
+            return list(members)
+
+    def get_coordinators(self):
+        return self.get_members_by_role_exact('coordinator', only_active=False)
 
     def get_committers_exact(self):
         return self.get_members_by_role_exact('committer')
@@ -164,17 +152,17 @@ class Team(models.Model):
     def get_translators_exact(self):
         return self.get_members_by_role_exact('translator')
 
-    def get_members_by_roles(self, roles):
+    def get_members_by_roles(self, roles, only_active=True):
         """Requires a list of roles in argument"""
         try:
             members = []
             for role in roles:
                 members += self.roles[role]
-        except:
-            members = list(Person.objects.filter(role__team__id=self.id,
-                                                 role__role__in=roles,
-                                                 role__is_active=True))
-        return members
+        except KeyError:
+            members = Person.objects.filter(role__team__id=self.id, role__role__in=roles)
+            if only_active:
+                members = members.filter(role__is_active=True)
+        return list(members)
 
     def get_committers(self):
         return self.get_members_by_roles(['coordinator', 'committer'])
@@ -188,7 +176,7 @@ class Team(models.Model):
             members = []
             for role in ['coordinator', 'committer', 'reviewer', 'translator']:
                 members += self.roles[role]
-        except:
+        except KeyError:
             # Not necessary to filter as for other roles
             members = list(self.members.all())
         return members
@@ -202,8 +190,8 @@ class Team(models.Model):
     def send_mail_to_coordinator(self, subject, message, messagekw={}):
         """ Send a message to the coordinator, in her language if available
             and if subject and message are lazy strings """
-        coordinator = self.get_coordinator()
-        if not coordinator or not coordinator.email:
+        recipients = [pers.email for pers in self.get_coordinators() if pers.email]
+        if not recipients:
             return
         prev_lang = translation.get_language()
         translation.activate(self.language_set.all()[0].locale)
@@ -214,7 +202,7 @@ class Team(models.Model):
             subject,
             message,
             settings.DEFAULT_FROM_EMAIL,
-            [coordinator.email]
+            recipients
         )
         translation.activate(prev_lang)
 
@@ -242,8 +230,8 @@ class FakeTeam(object):
     def get_languages(self):
         return (self.language,)
 
-    def get_coordinator(self):
-        return None
+    def get_coordinators(self):
+        return []
 
 
 ROLE_CHOICES = (
diff --git a/teams/tests.py b/teams/tests.py
index 3382bf2..cf87405 100644
--- a/teams/tests.py
+++ b/teams/tests.py
@@ -18,47 +18,33 @@ class TeamsAndRolesTests(TestCase):
         self.pn.set_password('password')
         self.pn.save()
 
-        self.pt = Person(first_name='John', last_name='Translator',
+        self.pt = Person.objects.create(first_name='John', last_name='Translator',
             email='jt tf1 com', username= 'jt')
-        self.pt.save()
 
-        self.pr = Person(first_name='John', last_name='Reviewer',
+        self.pr = Person.objects.create(first_name='John', last_name='Reviewer',
             email='jr csa com', username= 'jr')
-        self.pr.save()
 
-        self.pc = Person(first_name='John', last_name='Committer',
+        self.pc = Person.objects.create(first_name='John', last_name='Committer',
             email='jc alinsudesonpleingre fr', username= 'jc',
             last_login=datetime.now()-timedelta(days=30*6-1)) #active person, but in limit date
-        self.pc.save()
 
         self.pcoo = Person(first_name='John', last_name='Coordinator',
             email='jcoo imthebigboss fr', username= 'jcoo')
         self.pcoo.set_password('password')
         self.pcoo.save()
 
-        self.t = Team(name='fr', description='French', mailing_list='french_ml example org')
-        self.t.save()
-
-        self.t2 = Team(name='pt', description='Portuguese')
-        self.t2.save()
-
-        self.l = Language(name='French', locale='fr', team=self.t)
-        self.l.save()
-
-        self.role = Role(team=self.t, person=self.pt)
-        self.role.save()
-
-        self.role = Role(team=self.t2, person=self.pt, role='reviewer')
-        self.role.save()
+        self.t = Team.objects.create(name='fr', description='French',
+            mailing_list='french_ml example org')
 
-        self.role = Role(team=self.t, person=self.pr, role='reviewer')
-        self.role.save()
+        self.t2 = Team.objects.create(name='pt', description='Portuguese')
 
-        self.role = Role(team=self.t, person=self.pc, role='committer')
-        self.role.save()
+        self.l = Language.objects.create(name='French', locale='fr', team=self.t)
 
-        self.role = Role(team=self.t, person=self.pcoo, role='coordinator')
-        self.role.save()
+        _ = Role.objects.create(team=self.t, person=self.pt)
+        _ = Role.objects.create(team=self.t2, person=self.pt, role='reviewer')
+        _ = Role.objects.create(team=self.t, person=self.pr, role='reviewer')
+        _ = Role.objects.create(team=self.t, person=self.pc, role='committer')
+        _ = Role.objects.create(team=self.t, person=self.pcoo, role='coordinator')
 
 class TeamTest(TeamsAndRolesTests):
     def setUp(self):
@@ -91,8 +77,8 @@ class TeamTest(TeamsAndRolesTests):
         self.assertEqual(members[0], self.pc)
 
     def run_roles_exact_test(self, team):
-        pcoo = team.get_coordinator()
-        self.assertEqual(pcoo, self.pcoo)
+        pcoords = team.get_coordinators()
+        self.assertEqual(pcoords[0], self.pcoo)
 
         members = team.get_committers_exact()
         self.assert_(len(members), 1)
diff --git a/teams/views.py b/teams/views.py
index ebe0c39..e598646 100644
--- a/teams/views.py
+++ b/teams/views.py
@@ -46,7 +46,6 @@ def teams(request, format='html'):
 def team(request, team_slug):
     try:
         team = Team.objects.get(name=team_slug)
-        coordinator = team.get_coordinator()
         mem_groups = (
                {'title': _("Committers"),
                 'members': team.get_committers_exact(),
@@ -72,7 +71,6 @@ def team(request, team_slug):
     except Team.DoesNotExist:
         lang = get_object_or_404(Language, locale=team_slug)
         team = FakeTeam(lang)
-        coordinator = None
         mem_groups = ()
 
     context = {
diff --git a/templates/teams/team_base.html b/templates/teams/team_base.html
index 39c9d26..5e8ba8a 100644
--- a/templates/teams/team_base.html
+++ b/templates/teams/team_base.html
@@ -45,14 +45,12 @@
 
     <div class="bloc half">
         <h2>{% trans "Coordinator" %}</h2>
-        {% if team.get_coordinator %}
-          {% with team.get_coordinator as person %}
+        {% for person in team.get_coordinators %}
           {% include "people/person_overview.html" %}
-          {% endwith %}
-        {% else %}
+        {% empty %}
           <p><em>{% trans "This team has currently no coordinator." %}<br>
              {% blocktrans with link="http://live.gnome.org/TranslationProject/TeamCoordinatorResponsibilities"; %}See <a href="{{ link }}">the GTP Wiki</a> for more information about coordinatorship.{% endblocktrans %}</em></p>
-        {% endif %}
+        {% endfor %}
     </div>
 
 </div>
diff --git a/templates/teams/team_list.html b/templates/teams/team_list.html
index 2aaf852..8014034 100644
--- a/templates/teams/team_list.html
+++ b/templates/teams/team_list.html
@@ -1,5 +1,5 @@
 {% extends "base.html" %}
-{% load i18n %}
+{% load i18n people %}
 
 {% block title %}{% trans "GNOME Translation Teams" %}{% endblock %}
 
@@ -22,14 +22,12 @@
         <a href="{{ team.get_absolute_url }}">{{ team.translated_name }}</a>
         &mdash;
         <span style="font-size: 80%;">
-          {% with team.get_coordinator as coordinator %}
-          {% if coordinator %}
-            {% blocktrans with coordinator.get_absolute_url|safe as url and coordinator.name as name %}Coordinated by <a href="{{ url }}">{{ name }}</a>{% endblocktrans %}
+          {% if team.get_coordinators %}
+            {% blocktrans with plist=team.get_coordinators|people_list %}Coordinated by {{ plist }}</a>{% endblocktrans %}
           {% else %}
             <em>{% trans "No coordinator" %}</em>
           {% endif %}
         </span>
-        {% endwith %}
       </li>
       {% endfor %}
     </ul>
diff --git a/templates/teams/team_list.xml b/templates/teams/team_list.xml
index 2c92394..9556c07 100644
--- a/templates/teams/team_list.xml
+++ b/templates/teams/team_list.xml
@@ -1,15 +1,13 @@
 <teams>
   {% for team in teams %}
   <team id="{{ team.name }}">
-    {% with team.get_coordinator as coordinator %}
     <description>{{ team.description }}</description>
-    {% if coordinator and coordinator.svn_account %}
+    {% for coordinator in team.get_coordinators %}
     <coordinator>
       <name>{{ coordinator.name }}</name>
-      <vcs>{{ coordinator.svn_account }}</vcs>
+      {% if coordinator.svn_account %}<vcs>{{ coordinator.svn_account }}</vcs>{% endif %}
     </coordinator>
-    {% endif %}
-    {% endwith %}
+    {% endfor %}
   </team>
   {% endfor %}
 </teams>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]