We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
preclude adding stub participants as team members
Reticketed from #2362.

preclude adding stub participants as team members
Reticketed from #2362.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `gittip/models/_mixin_team.py`
Content:
```
1 """Teams on Gittip are plural participants with members.
2 """
3 from decimal import Decimal
4 
5 from aspen.utils import typecheck
6 
7 
8 class MemberLimitReached(Exception): pass
9 
10 
11 class MixinTeam(object):
12     """This class provides methods for working with a Participant as a Team.
13 
14     :param Participant participant: the underlying :py:class:`~gittip.participant.Participant` object for this team
15 
16     """
17 
18     # XXX These were all written with the ORM and need to be converted.
19 
20     def __init__(self, participant):
21         self.participant = participant
22 
23     def show_as_team(self, user):
24         """Return a boolean, whether to show this participant as a team.
25         """
26         if not self.IS_PLURAL:
27             return False
28         if user.ADMIN:
29             return True
30         if not self.get_takes():
31             if self == user.participant:
32                 return True
33             return False
34         return True
35 
36     def add_member(self, member):
37         """Add a member to this team.
38         """
39         assert self.IS_PLURAL
40         if len(self.get_takes()) == 149:
41             raise MemberLimitReached
42         self.__set_take_for(member, Decimal('0.01'), self)
43 
44     def remove_member(self, member):
45         """Remove a member from this team.
46         """
47         assert self.IS_PLURAL
48         self.__set_take_for(member, Decimal('0.00'), self)
49 
50     def member_of(self, team):
51         """Given a Participant object, return a boolean.
52         """
53         assert team.IS_PLURAL
54         for take in team.get_takes():
55             if take['member'] == self.username:
56                 return True
57         return False
58 
59     def get_take_last_week_for(self, member):
60         """What did the user actually take most recently? Used in throttling.
61         """
62         assert self.IS_PLURAL
63         membername = member.username if hasattr(member, 'username') \
64                                                         else member['username']
65         return self.db.one("""
66 
67             SELECT amount
68               FROM transfers
69              WHERE tipper=%s AND tippee=%s
70                AND timestamp >
71                 (SELECT ts_start FROM paydays ORDER BY ts_start DESC LIMIT 1)
72           ORDER BY timestamp DESC LIMIT 1
73 
74         """, (self.username, membername), default=Decimal('0.00'))
75 
76     def get_take_for(self, member):
77         """Return a Decimal representation of the take for this member, or 0.
78         """
79         assert self.IS_PLURAL
80         return self.db.one( "SELECT amount FROM current_takes "
81                             "WHERE member=%s AND team=%s"
82                           , (member.username, self.username)
83                           , default=Decimal('0.00')
84                            )
85 
86     def compute_max_this_week(self, last_week):
87         """2x last week's take, but at least a dollar.
88         """
89         return max(last_week * Decimal('2'), Decimal('1.00'))
90 
91     def set_take_for(self, member, take, recorder):
92         """Sets member's take from the team pool.
93         """
94         assert self.IS_PLURAL
95 
96         # lazy import to avoid circular import
97         from gittip.security.user import User
98         from gittip.models.participant import Participant
99 
100         typecheck( member, Participant
101                  , take, Decimal
102                  , recorder, (Participant, User)
103                   )
104 
105         last_week = self.get_take_last_week_for(member)
106         max_this_week = self.compute_max_this_week(last_week)
107         if take > max_this_week:
108             take = max_this_week
109 
110         self.__set_take_for(member, take, recorder)
111         return take
112 
113     def __set_take_for(self, member, amount, recorder):
114         assert self.IS_PLURAL
115         # XXX Factored out for testing purposes only! :O Use .set_take_for.
116         self.db.run("""
117 
118             INSERT INTO takes (ctime, member, team, amount, recorder)
119              VALUES ( COALESCE (( SELECT ctime
120                                     FROM takes
121                                    WHERE member=%s
122                                      AND team=%s
123                                    LIMIT 1
124                                  ), CURRENT_TIMESTAMP)
125                     , %s
126                     , %s
127                     , %s
128                     , %s
129                      )
130 
131         """, (member.username, self.username, member.username, self.username, \
132                                                       amount, recorder.username))
133 
134     def get_takes(self, for_payday=False):
135         """Return a list of member takes for a team.
136 
137         This is implemented parallel to Participant.get_tips_and_total. See
138         over there for an explanation of for_payday.
139 
140         """
141         assert self.IS_PLURAL
142 
143         args = dict(team=self.username)
144 
145         if for_payday:
146             args['ts_start'] = for_payday
147 
148             # Get the takes for this team, as they were before ts_start,
149             # filtering out the ones we've already transferred (in case payday
150             # is interrupted and restarted).
151 
152             TAKES = """\
153 
154                 SELECT * FROM (
155                      SELECT DISTINCT ON (member) t.*
156                        FROM takes t
157                        JOIN participants p ON p.username = member
158                       WHERE team=%(team)s
159                         AND mtime < %(ts_start)s
160                         AND p.is_suspicious IS NOT true
161                         AND ( SELECT id
162                                 FROM transfers
163                                WHERE tipper=t.team
164                                  AND tippee=t.member
165                                  AND as_team_member IS true
166                                  AND timestamp >= %(ts_start)s
167                              ) IS NULL
168                    ORDER BY member, mtime DESC
169                 ) AS foo
170                 ORDER BY ctime DESC
171 
172             """
173         else:
174             TAKES = """\
175 
176                 SELECT member, amount, ctime, mtime
177                   FROM current_takes
178                  WHERE team=%(team)s
179               ORDER BY ctime DESC
180 
181             """
182 
183         return self.db.all(TAKES, args, back_as=dict)
184 
185     def get_team_take(self):
186         """Return a single take for a team, the team itself's take.
187         """
188         assert self.IS_PLURAL
189         TAKE = "SELECT sum(amount) FROM current_takes WHERE team=%s"
190         total_take = self.db.one(TAKE, (self.username,), default=0)
191         team_take = max(self.get_dollars_receiving() - total_take, 0)
192         membership = { "ctime": None
193                      , "mtime": None
194                      , "member": self.username
195                      , "amount": team_take
196                       }
197         return membership
198 
199     def get_members(self, current_participant):
200         """Return a list of member dicts.
201         """
202         assert self.IS_PLURAL
203         takes = self.get_takes()
204         takes.append(self.get_team_take())
205         budget = balance = self.get_dollars_receiving()
206         members = []
207         for take in takes:
208             member = {}
209             member['username'] = take['member']
210             member['take'] = take['amount']
211 
212             member['removal_allowed'] = current_participant == self
213             member['editing_allowed'] = False
214             member['is_current_user'] = False
215             if current_participant is not None:
216                 if member['username'] == current_participant.username:
217                     member['is_current_user'] = True
218                     if take['ctime'] is not None:
219                         # current user, but not the team itself
220                         member['editing_allowed']= True
221 
222             member['last_week'] = last_week = self.get_take_last_week_for(member)
223             member['max_this_week'] = self.compute_max_this_week(last_week)
224             amount = min(take['amount'], balance)
225             balance -= amount
226             member['balance'] = balance
227             member['percentage'] = (amount / budget) if budget > 0 else 0
228             members.append(member)
229         return members
230
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/gittip/models/_mixin_team.py b/gittip/models/_mixin_team.py
--- a/gittip/models/_mixin_team.py
+++ b/gittip/models/_mixin_team.py
@@ -7,6 +7,7 @@
 
 class MemberLimitReached(Exception): pass
 
+class StubParticipantAdded(Exception): pass
 
 class MixinTeam(object):
     """This class provides methods for working with a Participant as a Team.
@@ -39,6 +40,8 @@
         assert self.IS_PLURAL
         if len(self.get_takes()) == 149:
             raise MemberLimitReached
+        if not member.is_claimed:
+            raise StubParticipantAdded
         self.__set_take_for(member, Decimal('0.01'), self)
 
     def remove_member(self, member):

{"golden_diff": "diff --git a/gittip/models/_mixin_team.py b/gittip/models/_mixin_team.py\n--- a/gittip/models/_mixin_team.py\n+++ b/gittip/models/_mixin_team.py\n@@ -7,6 +7,7 @@\n \n class MemberLimitReached(Exception): pass\n \n+class StubParticipantAdded(Exception): pass\n \n class MixinTeam(object):\n     \"\"\"This class provides methods for working with a Participant as a Team.\n@@ -39,6 +40,8 @@\n         assert self.IS_PLURAL\n         if len(self.get_takes()) == 149:\n             raise MemberLimitReached\n+        if not member.is_claimed:\n+            raise StubParticipantAdded\n         self.__set_take_for(member, Decimal('0.01'), self)\n \n     def remove_member(self, member):\n", "issue": "preclude adding stub participants as team members\nReticketed from #2362.\n\npreclude adding stub participants as team members\nReticketed from #2362.\n\n", "before_files": [{"content": "\"\"\"Teams on Gittip are plural participants with members.\n\"\"\"\nfrom decimal import Decimal\n\nfrom aspen.utils import typecheck\n\n\nclass MemberLimitReached(Exception): pass\n\n\nclass MixinTeam(object):\n    \"\"\"This class provides methods for working with a Participant as a Team.\n\n    :param Participant participant: the underlying :py:class:`~gittip.participant.Participant` object for this team\n\n    \"\"\"\n\n    # XXX These were all written with the ORM and need to be converted.\n\n    def __init__(self, participant):\n        self.participant = participant\n\n    def show_as_team(self, user):\n        \"\"\"Return a boolean, whether to show this participant as a team.\n        \"\"\"\n        if not self.IS_PLURAL:\n            return False\n        if user.ADMIN:\n            return True\n        if not self.get_takes():\n            if self == user.participant:\n                return True\n            return False\n        return True\n\n    def add_member(self, member):\n        \"\"\"Add a member to this team.\n        \"\"\"\n        assert self.IS_PLURAL\n        if len(self.get_takes()) == 149:\n            raise MemberLimitReached\n        self.__set_take_for(member, Decimal('0.01'), self)\n\n    def remove_member(self, member):\n        \"\"\"Remove a member from this team.\n        \"\"\"\n        assert self.IS_PLURAL\n        self.__set_take_for(member, Decimal('0.00'), self)\n\n    def member_of(self, team):\n        \"\"\"Given a Participant object, return a boolean.\n        \"\"\"\n        assert team.IS_PLURAL\n        for take in team.get_takes():\n            if take['member'] == self.username:\n                return True\n        return False\n\n    def get_take_last_week_for(self, member):\n        \"\"\"What did the user actually take most recently? Used in throttling.\n        \"\"\"\n        assert self.IS_PLURAL\n        membername = member.username if hasattr(member, 'username') \\\n                                                        else member['username']\n        return self.db.one(\"\"\"\n\n            SELECT amount\n              FROM transfers\n             WHERE tipper=%s AND tippee=%s\n               AND timestamp >\n                (SELECT ts_start FROM paydays ORDER BY ts_start DESC LIMIT 1)\n          ORDER BY timestamp DESC LIMIT 1\n\n        \"\"\", (self.username, membername), default=Decimal('0.00'))\n\n    def get_take_for(self, member):\n        \"\"\"Return a Decimal representation of the take for this member, or 0.\n        \"\"\"\n        assert self.IS_PLURAL\n        return self.db.one( \"SELECT amount FROM current_takes \"\n                            \"WHERE member=%s AND team=%s\"\n                          , (member.username, self.username)\n                          , default=Decimal('0.00')\n                           )\n\n    def compute_max_this_week(self, last_week):\n        \"\"\"2x last week's take, but at least a dollar.\n        \"\"\"\n        return max(last_week * Decimal('2'), Decimal('1.00'))\n\n    def set_take_for(self, member, take, recorder):\n        \"\"\"Sets member's take from the team pool.\n        \"\"\"\n        assert self.IS_PLURAL\n\n        # lazy import to avoid circular import\n        from gittip.security.user import User\n        from gittip.models.participant import Participant\n\n        typecheck( member, Participant\n                 , take, Decimal\n                 , recorder, (Participant, User)\n                  )\n\n        last_week = self.get_take_last_week_for(member)\n        max_this_week = self.compute_max_this_week(last_week)\n        if take > max_this_week:\n            take = max_this_week\n\n        self.__set_take_for(member, take, recorder)\n        return take\n\n    def __set_take_for(self, member, amount, recorder):\n        assert self.IS_PLURAL\n        # XXX Factored out for testing purposes only! :O Use .set_take_for.\n        self.db.run(\"\"\"\n\n            INSERT INTO takes (ctime, member, team, amount, recorder)\n             VALUES ( COALESCE (( SELECT ctime\n                                    FROM takes\n                                   WHERE member=%s\n                                     AND team=%s\n                                   LIMIT 1\n                                 ), CURRENT_TIMESTAMP)\n                    , %s\n                    , %s\n                    , %s\n                    , %s\n                     )\n\n        \"\"\", (member.username, self.username, member.username, self.username, \\\n                                                      amount, recorder.username))\n\n    def get_takes(self, for_payday=False):\n        \"\"\"Return a list of member takes for a team.\n\n        This is implemented parallel to Participant.get_tips_and_total. See\n        over there for an explanation of for_payday.\n\n        \"\"\"\n        assert self.IS_PLURAL\n\n        args = dict(team=self.username)\n\n        if for_payday:\n            args['ts_start'] = for_payday\n\n            # Get the takes for this team, as they were before ts_start,\n            # filtering out the ones we've already transferred (in case payday\n            # is interrupted and restarted).\n\n            TAKES = \"\"\"\\\n\n                SELECT * FROM (\n                     SELECT DISTINCT ON (member) t.*\n                       FROM takes t\n                       JOIN participants p ON p.username = member\n                      WHERE team=%(team)s\n                        AND mtime < %(ts_start)s\n                        AND p.is_suspicious IS NOT true\n                        AND ( SELECT id\n                                FROM transfers\n                               WHERE tipper=t.team\n                                 AND tippee=t.member\n                                 AND as_team_member IS true\n                                 AND timestamp >= %(ts_start)s\n                             ) IS NULL\n                   ORDER BY member, mtime DESC\n                ) AS foo\n                ORDER BY ctime DESC\n\n            \"\"\"\n        else:\n            TAKES = \"\"\"\\\n\n                SELECT member, amount, ctime, mtime\n                  FROM current_takes\n                 WHERE team=%(team)s\n              ORDER BY ctime DESC\n\n            \"\"\"\n\n        return self.db.all(TAKES, args, back_as=dict)\n\n    def get_team_take(self):\n        \"\"\"Return a single take for a team, the team itself's take.\n        \"\"\"\n        assert self.IS_PLURAL\n        TAKE = \"SELECT sum(amount) FROM current_takes WHERE team=%s\"\n        total_take = self.db.one(TAKE, (self.username,), default=0)\n        team_take = max(self.get_dollars_receiving() - total_take, 0)\n        membership = { \"ctime\": None\n                     , \"mtime\": None\n                     , \"member\": self.username\n                     , \"amount\": team_take\n                      }\n        return membership\n\n    def get_members(self, current_participant):\n        \"\"\"Return a list of member dicts.\n        \"\"\"\n        assert self.IS_PLURAL\n        takes = self.get_takes()\n        takes.append(self.get_team_take())\n        budget = balance = self.get_dollars_receiving()\n        members = []\n        for take in takes:\n            member = {}\n            member['username'] = take['member']\n            member['take'] = take['amount']\n\n            member['removal_allowed'] = current_participant == self\n            member['editing_allowed'] = False\n            member['is_current_user'] = False\n            if current_participant is not None:\n                if member['username'] == current_participant.username:\n                    member['is_current_user'] = True\n                    if take['ctime'] is not None:\n                        # current user, but not the team itself\n                        member['editing_allowed']= True\n\n            member['last_week'] = last_week = self.get_take_last_week_for(member)\n            member['max_this_week'] = self.compute_max_this_week(last_week)\n            amount = min(take['amount'], balance)\n            balance -= amount\n            member['balance'] = balance\n            member['percentage'] = (amount / budget) if budget > 0 else 0\n            members.append(member)\n        return members\n", "path": "gittip/models/_mixin_team.py"}], "after_files": [{"content": "\"\"\"Teams on Gittip are plural participants with members.\n\"\"\"\nfrom decimal import Decimal\n\nfrom aspen.utils import typecheck\n\n\nclass MemberLimitReached(Exception): pass\n\nclass StubParticipantAdded(Exception): pass\n\nclass MixinTeam(object):\n    \"\"\"This class provides methods for working with a Participant as a Team.\n\n    :param Participant participant: the underlying :py:class:`~gittip.participant.Participant` object for this team\n\n    \"\"\"\n\n    # XXX These were all written with the ORM and need to be converted.\n\n    def __init__(self, participant):\n        self.participant = participant\n\n    def show_as_team(self, user):\n        \"\"\"Return a boolean, whether to show this participant as a team.\n        \"\"\"\n        if not self.IS_PLURAL:\n            return False\n        if user.ADMIN:\n            return True\n        if not self.get_takes():\n            if self == user.participant:\n                return True\n            return False\n        return True\n\n    def add_member(self, member):\n        \"\"\"Add a member to this team.\n        \"\"\"\n        assert self.IS_PLURAL\n        if len(self.get_takes()) == 149:\n            raise MemberLimitReached\n        if not member.is_claimed:\n            raise StubParticipantAdded\n        self.__set_take_for(member, Decimal('0.01'), self)\n\n    def remove_member(self, member):\n        \"\"\"Remove a member from this team.\n        \"\"\"\n        assert self.IS_PLURAL\n        self.__set_take_for(member, Decimal('0.00'), self)\n\n    def member_of(self, team):\n        \"\"\"Given a Participant object, return a boolean.\n        \"\"\"\n        assert team.IS_PLURAL\n        for take in team.get_takes():\n            if take['member'] == self.username:\n                return True\n        return False\n\n    def get_take_last_week_for(self, member):\n        \"\"\"What did the user actually take most recently? Used in throttling.\n        \"\"\"\n        assert self.IS_PLURAL\n        membername = member.username if hasattr(member, 'username') \\\n                                                        else member['username']\n        return self.db.one(\"\"\"\n\n            SELECT amount\n              FROM transfers\n             WHERE tipper=%s AND tippee=%s\n               AND timestamp >\n                (SELECT ts_start FROM paydays ORDER BY ts_start DESC LIMIT 1)\n          ORDER BY timestamp DESC LIMIT 1\n\n        \"\"\", (self.username, membername), default=Decimal('0.00'))\n\n    def get_take_for(self, member):\n        \"\"\"Return a Decimal representation of the take for this member, or 0.\n        \"\"\"\n        assert self.IS_PLURAL\n        return self.db.one( \"SELECT amount FROM current_takes \"\n                            \"WHERE member=%s AND team=%s\"\n                          , (member.username, self.username)\n                          , default=Decimal('0.00')\n                           )\n\n    def compute_max_this_week(self, last_week):\n        \"\"\"2x last week's take, but at least a dollar.\n        \"\"\"\n        return max(last_week * Decimal('2'), Decimal('1.00'))\n\n    def set_take_for(self, member, take, recorder):\n        \"\"\"Sets member's take from the team pool.\n        \"\"\"\n        assert self.IS_PLURAL\n\n        # lazy import to avoid circular import\n        from gittip.security.user import User\n        from gittip.models.participant import Participant\n\n        typecheck( member, Participant\n                 , take, Decimal\n                 , recorder, (Participant, User)\n                  )\n\n        last_week = self.get_take_last_week_for(member)\n        max_this_week = self.compute_max_this_week(last_week)\n        if take > max_this_week:\n            take = max_this_week\n\n        self.__set_take_for(member, take, recorder)\n        return take\n\n    def __set_take_for(self, member, amount, recorder):\n        assert self.IS_PLURAL\n        # XXX Factored out for testing purposes only! :O Use .set_take_for.\n        self.db.run(\"\"\"\n\n            INSERT INTO takes (ctime, member, team, amount, recorder)\n             VALUES ( COALESCE (( SELECT ctime\n                                    FROM takes\n                                   WHERE member=%s\n                                     AND team=%s\n                                   LIMIT 1\n                                 ), CURRENT_TIMESTAMP)\n                    , %s\n                    , %s\n                    , %s\n                    , %s\n                     )\n\n        \"\"\", (member.username, self.username, member.username, self.username, \\\n                                                      amount, recorder.username))\n\n    def get_takes(self, for_payday=False):\n        \"\"\"Return a list of member takes for a team.\n\n        This is implemented parallel to Participant.get_tips_and_total. See\n        over there for an explanation of for_payday.\n\n        \"\"\"\n        assert self.IS_PLURAL\n\n        args = dict(team=self.username)\n\n        if for_payday:\n            args['ts_start'] = for_payday\n\n            # Get the takes for this team, as they were before ts_start,\n            # filtering out the ones we've already transferred (in case payday\n            # is interrupted and restarted).\n\n            TAKES = \"\"\"\\\n\n                SELECT * FROM (\n                     SELECT DISTINCT ON (member) t.*\n                       FROM takes t\n                       JOIN participants p ON p.username = member\n                      WHERE team=%(team)s\n                        AND mtime < %(ts_start)s\n                        AND p.is_suspicious IS NOT true\n                        AND ( SELECT id\n                                FROM transfers\n                               WHERE tipper=t.team\n                                 AND tippee=t.member\n                                 AND as_team_member IS true\n                                 AND timestamp >= %(ts_start)s\n                             ) IS NULL\n                   ORDER BY member, mtime DESC\n                ) AS foo\n                ORDER BY ctime DESC\n\n            \"\"\"\n        else:\n            TAKES = \"\"\"\\\n\n                SELECT member, amount, ctime, mtime\n                  FROM current_takes\n                 WHERE team=%(team)s\n              ORDER BY ctime DESC\n\n            \"\"\"\n\n        return self.db.all(TAKES, args, back_as=dict)\n\n    def get_team_take(self):\n        \"\"\"Return a single take for a team, the team itself's take.\n        \"\"\"\n        assert self.IS_PLURAL\n        TAKE = \"SELECT sum(amount) FROM current_takes WHERE team=%s\"\n        total_take = self.db.one(TAKE, (self.username,), default=0)\n        team_take = max(self.get_dollars_receiving() - total_take, 0)\n        membership = { \"ctime\": None\n                     , \"mtime\": None\n                     , \"member\": self.username\n                     , \"amount\": team_take\n                      }\n        return membership\n\n    def get_members(self, current_participant):\n        \"\"\"Return a list of member dicts.\n        \"\"\"\n        assert self.IS_PLURAL\n        takes = self.get_takes()\n        takes.append(self.get_team_take())\n        budget = balance = self.get_dollars_receiving()\n        members = []\n        for take in takes:\n            member = {}\n            member['username'] = take['member']\n            member['take'] = take['amount']\n\n            member['removal_allowed'] = current_participant == self\n            member['editing_allowed'] = False\n            member['is_current_user'] = False\n            if current_participant is not None:\n                if member['username'] == current_participant.username:\n                    member['is_current_user'] = True\n                    if take['ctime'] is not None:\n                        # current user, but not the team itself\n                        member['editing_allowed']= True\n\n            member['last_week'] = last_week = self.get_take_last_week_for(member)\n            member['max_this_week'] = self.compute_max_this_week(last_week)\n            amount = min(take['amount'], balance)\n            balance -= amount\n            member['balance'] = balance\n            member['percentage'] = (amount / budget) if budget > 0 else 0\n            members.append(member)\n        return members\n", "path": "gittip/models/_mixin_team.py"}]}