We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Don't subclass ThreadPool.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `master/contrib/googlecode_atom.py`
Content:
```
1 # GoogleCode Atom Feed Poller
2 # Author: Srivats P. <pstavirs>
3 # Based on Mozilla's HgPoller
4 #     http://bonsai.mozilla.org/cvsblame.cgi?file=/mozilla/tools/buildbot/buildbot/changes/Attic/hgpoller.py&revision=1.1.4.2
5 #
6 # Description:
7 #   Use this ChangeSource for projects hosted on http://code.google.com/
8 #
9 #   This ChangeSource uses the project's commit Atom feed. Depending upon the
10 #   frequency of commits, you can tune the polling interval for the feed
11 #   (default is 1 hour)
12 #
13 # Parameters:
14 #   feedurl (MANDATORY): The Atom feed URL of the GoogleCode repo
15 #   pollinterval (OPTIONAL): Polling frequency for the feed (in seconds)
16 #
17 # Example:
18 # To poll the Ostinato project's commit feed every 3 hours, use -
19 #   from googlecode_atom import GoogleCodeAtomPoller
20 #   poller = GoogleCodeAtomPoller(
21 #            feedurl="http://code.google.com/feeds/p/ostinato/hgchanges/basic",
22 #            pollinterval=10800)
23 #   c['change_source'] = [ poller ]
24 #
25 
26 from time import strptime
27 from calendar import timegm
28 from xml.dom import minidom, Node
29 
30 from twisted.python import log, failure
31 from twisted.internet import defer, reactor
32 from twisted.internet.task import LoopingCall
33 from twisted.web.client import getPage
34 
35 from buildbot.changes import base, changes
36 
37 def googleCodePollerForProject(project, vcs, pollinterval=3600):
38     return GoogleCodeAtomPoller(
39         'http://code.google.com/feeds/p/%s/%schanges/basic' % (project, vcs),
40         pollinterval=pollinterval)
41 
42 
43 class GoogleCodeAtomPoller(base.ChangeSource):
44     """This source will poll a GoogleCode Atom feed for changes and
45     submit them to the change master. Works for both Svn, Git, and Hg
46     repos.
47     TODO: branch processing
48     """
49 
50     compare_attrs = ['feedurl', 'pollinterval']
51     parent = None
52     loop = None
53     volatile = ['loop']
54     working = False
55 
56     def __init__(self, feedurl, pollinterval=3600):
57         """
58         @type   feedurl:        string
59         @param  feedurl:        The Atom feed URL of the GoogleCode repo
60                                 (e.g. http://code.google.com/feeds/p/ostinato/hgchanges/basic)
61 
62         @type   pollinterval:   int
63         @param  pollinterval:   The time (in seconds) between queries for
64                                 changes (default is 1 hour)
65         """
66 
67         self.feedurl = feedurl
68         self.branch = None
69         self.pollinterval = pollinterval
70         self.lastChange = None
71         self.loop = LoopingCall(self.poll)
72         self.src = None
73         for word in self.feedurl.split('/'):
74             if word == 'svnchanges':
75                 self.src = 'svn'
76                 break
77             elif word == 'hgchanges':
78                 self.src = 'hg'
79                 break
80             elif word == 'gitchanges':
81                 self.src = 'git'
82                 break
83 
84     def startService(self):
85         log.msg("GoogleCodeAtomPoller starting")
86         base.ChangeSource.startService(self)
87         reactor.callLater(0, self.loop.start, self.pollinterval)
88 
89     def stopService(self):
90         log.msg("GoogleCodeAtomPoller stoppping")
91         self.loop.stop()
92         return base.ChangeSource.stopService(self)
93 
94     def describe(self):
95         return ("Getting changes from the GoogleCode repo changes feed %s" %
96                self._make_url())
97 
98     def poll(self):
99         if self.working:
100             log.msg("Not polling because last poll is still working")
101         else:
102             self.working = True
103             d = self._get_changes()
104             d.addCallback(self._process_changes)
105             d.addCallbacks(self._finished_ok, self._finished_failure)
106 
107     def _finished_ok(self, res):
108         assert self.working
109         self.working = False
110         log.msg("GoogleCodeAtomPoller poll success")
111 
112         return res
113 
114     def _finished_failure(self, res):
115         log.msg("GoogleCodeAtomPoller poll failed: %s" % res)
116         assert self.working
117         self.working = False
118         return None
119 
120     def _make_url(self):
121         return "%s" % (self.feedurl)
122 
123     def _get_changes(self):
124         url = self._make_url()
125         log.msg("GoogleCodeAtomPoller polling %s" % url)
126 
127         return getPage(url, timeout=self.pollinterval)
128 
129     def _parse_changes(self, query):
130         dom = minidom.parseString(query)
131         entries = dom.getElementsByTagName("entry")
132         changes = []
133         # Entries come in reverse chronological order
134         for i in entries:
135             d = {}
136 
137             # revision is the last part of the 'id' url
138             d["revision"] = i.getElementsByTagName(
139                 "id")[0].firstChild.data.split('/')[-1]
140             if d["revision"] == self.lastChange:
141                 break  # no more new changes
142 
143             d["when"] = timegm(strptime(
144                 i.getElementsByTagName("updated")[0].firstChild.data,
145                 "%Y-%m-%dT%H:%M:%SZ"))
146             d["author"] = i.getElementsByTagName(
147                 "author")[0].getElementsByTagName("name")[0].firstChild.data
148             # files and commit msg are separated by 2 consecutive <br/>
149             content = i.getElementsByTagName(
150                 "content")[0].firstChild.data.split("<br/>\n <br/>")
151             # Remove the action keywords from the file list
152             fl = content[0].replace(
153                 u' \xa0\xa0\xa0\xa0Add\xa0\xa0\xa0\xa0', '').replace(
154                 u' \xa0\xa0\xa0\xa0Delete\xa0\xa0\xa0\xa0', '').replace(
155                 u' \xa0\xa0\xa0\xa0Modify\xa0\xa0\xa0\xa0', '')
156             # Get individual files and remove the 'header'
157             d["files"] = fl.encode("ascii", "replace").split("<br/>")[1:]
158             d["files"] = [f.strip() for f in d["files"]]
159             try:
160                 d["comments"] = content[1].encode("ascii", "replace")
161             except:
162                 d["comments"] = "No commit message provided"
163 
164             changes.append(d)
165 
166         changes.reverse() # want them in chronological order
167         return changes
168 
169     def _process_changes(self, query):
170         change_list = self._parse_changes(query)
171 
172         # Skip calling addChange() if this is the first successful poll.
173         if self.lastChange is not None:
174             for change in change_list:
175                 c = changes.Change(revision = change["revision"],
176                                    who = change["author"],
177                                    files = change["files"],
178                                    comments = change["comments"],
179                                    when = change["when"],
180                                    branch = self.branch)
181                 self.parent.addChange(c, src=self.src)
182         if change_list:
183             self.lastChange = change_list[-1]["revision"]
184
```
--- 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/master/contrib/googlecode_atom.py b/master/contrib/googlecode_atom.py
--- a/master/contrib/googlecode_atom.py
+++ b/master/contrib/googlecode_atom.py
@@ -23,8 +23,7 @@
 #   c['change_source'] = [ poller ]
 #
 
-from time import strptime
-from calendar import timegm
+import datetime
 from xml.dom import minidom, Node
 
 from twisted.python import log, failure
@@ -32,7 +31,8 @@
 from twisted.internet.task import LoopingCall
 from twisted.web.client import getPage
 
-from buildbot.changes import base, changes
+from buildbot.changes import base
+
 
 def googleCodePollerForProject(project, vcs, pollinterval=3600):
     return GoogleCodeAtomPoller(
@@ -140,9 +140,9 @@
             if d["revision"] == self.lastChange:
                 break  # no more new changes
 
-            d["when"] = timegm(strptime(
+            d["when"] = datetime.datetime.strptime(
                 i.getElementsByTagName("updated")[0].firstChild.data,
-                "%Y-%m-%dT%H:%M:%SZ"))
+                "%Y-%m-%dT%H:%M:%SZ")
             d["author"] = i.getElementsByTagName(
                 "author")[0].getElementsByTagName("name")[0].firstChild.data
             # files and commit msg are separated by 2 consecutive <br/>
@@ -166,18 +166,22 @@
         changes.reverse() # want them in chronological order
         return changes
 
+    @defer.deferredGenerator
     def _process_changes(self, query):
         change_list = self._parse_changes(query)
 
         # Skip calling addChange() if this is the first successful poll.
         if self.lastChange is not None:
             for change in change_list:
-                c = changes.Change(revision = change["revision"],
-                                   who = change["author"],
-                                   files = change["files"],
-                                   comments = change["comments"],
-                                   when = change["when"],
-                                   branch = self.branch)
-                self.parent.addChange(c, src=self.src)
+                d = self.master.addChange(author=change["author"],
+                                          revision=change["revision"],
+                                          files=change["files"],
+                                          comments=change["comments"],
+                                          when_timestamp=change["when"],
+                                          branch=self.branch,
+                                          src=self.src)
+                wfd = defer.waitForDeferred(d)
+                yield wfd
+                results = wfd.getResult()
         if change_list:
             self.lastChange = change_list[-1]["revision"]

{"golden_diff": "diff --git a/master/contrib/googlecode_atom.py b/master/contrib/googlecode_atom.py\n--- a/master/contrib/googlecode_atom.py\n+++ b/master/contrib/googlecode_atom.py\n@@ -23,8 +23,7 @@\n #   c['change_source'] = [ poller ]\n #\n \n-from time import strptime\n-from calendar import timegm\n+import datetime\n from xml.dom import minidom, Node\n \n from twisted.python import log, failure\n@@ -32,7 +31,8 @@\n from twisted.internet.task import LoopingCall\n from twisted.web.client import getPage\n \n-from buildbot.changes import base, changes\n+from buildbot.changes import base\n+\n \n def googleCodePollerForProject(project, vcs, pollinterval=3600):\n     return GoogleCodeAtomPoller(\n@@ -140,9 +140,9 @@\n             if d[\"revision\"] == self.lastChange:\n                 break  # no more new changes\n \n-            d[\"when\"] = timegm(strptime(\n+            d[\"when\"] = datetime.datetime.strptime(\n                 i.getElementsByTagName(\"updated\")[0].firstChild.data,\n-                \"%Y-%m-%dT%H:%M:%SZ\"))\n+                \"%Y-%m-%dT%H:%M:%SZ\")\n             d[\"author\"] = i.getElementsByTagName(\n                 \"author\")[0].getElementsByTagName(\"name\")[0].firstChild.data\n             # files and commit msg are separated by 2 consecutive <br/>\n@@ -166,18 +166,22 @@\n         changes.reverse() # want them in chronological order\n         return changes\n \n+    @defer.deferredGenerator\n     def _process_changes(self, query):\n         change_list = self._parse_changes(query)\n \n         # Skip calling addChange() if this is the first successful poll.\n         if self.lastChange is not None:\n             for change in change_list:\n-                c = changes.Change(revision = change[\"revision\"],\n-                                   who = change[\"author\"],\n-                                   files = change[\"files\"],\n-                                   comments = change[\"comments\"],\n-                                   when = change[\"when\"],\n-                                   branch = self.branch)\n-                self.parent.addChange(c, src=self.src)\n+                d = self.master.addChange(author=change[\"author\"],\n+                                          revision=change[\"revision\"],\n+                                          files=change[\"files\"],\n+                                          comments=change[\"comments\"],\n+                                          when_timestamp=change[\"when\"],\n+                                          branch=self.branch,\n+                                          src=self.src)\n+                wfd = defer.waitForDeferred(d)\n+                yield wfd\n+                results = wfd.getResult()\n         if change_list:\n             self.lastChange = change_list[-1][\"revision\"]\n", "issue": "Don't subclass ThreadPool.\n\n", "before_files": [{"content": "# GoogleCode Atom Feed Poller\n# Author: Srivats P. <pstavirs>\n# Based on Mozilla's HgPoller\n#     http://bonsai.mozilla.org/cvsblame.cgi?file=/mozilla/tools/buildbot/buildbot/changes/Attic/hgpoller.py&revision=1.1.4.2\n#\n# Description:\n#   Use this ChangeSource for projects hosted on http://code.google.com/\n#\n#   This ChangeSource uses the project's commit Atom feed. Depending upon the\n#   frequency of commits, you can tune the polling interval for the feed\n#   (default is 1 hour)\n#\n# Parameters:\n#   feedurl (MANDATORY): The Atom feed URL of the GoogleCode repo\n#   pollinterval (OPTIONAL): Polling frequency for the feed (in seconds)\n#\n# Example:\n# To poll the Ostinato project's commit feed every 3 hours, use -\n#   from googlecode_atom import GoogleCodeAtomPoller\n#   poller = GoogleCodeAtomPoller(\n#            feedurl=\"http://code.google.com/feeds/p/ostinato/hgchanges/basic\",\n#            pollinterval=10800)\n#   c['change_source'] = [ poller ]\n#\n\nfrom time import strptime\nfrom calendar import timegm\nfrom xml.dom import minidom, Node\n\nfrom twisted.python import log, failure\nfrom twisted.internet import defer, reactor\nfrom twisted.internet.task import LoopingCall\nfrom twisted.web.client import getPage\n\nfrom buildbot.changes import base, changes\n\ndef googleCodePollerForProject(project, vcs, pollinterval=3600):\n    return GoogleCodeAtomPoller(\n        'http://code.google.com/feeds/p/%s/%schanges/basic' % (project, vcs),\n        pollinterval=pollinterval)\n\n\nclass GoogleCodeAtomPoller(base.ChangeSource):\n    \"\"\"This source will poll a GoogleCode Atom feed for changes and\n    submit them to the change master. Works for both Svn, Git, and Hg\n    repos.\n    TODO: branch processing\n    \"\"\"\n\n    compare_attrs = ['feedurl', 'pollinterval']\n    parent = None\n    loop = None\n    volatile = ['loop']\n    working = False\n\n    def __init__(self, feedurl, pollinterval=3600):\n        \"\"\"\n        @type   feedurl:        string\n        @param  feedurl:        The Atom feed URL of the GoogleCode repo\n                                (e.g. http://code.google.com/feeds/p/ostinato/hgchanges/basic)\n\n        @type   pollinterval:   int\n        @param  pollinterval:   The time (in seconds) between queries for\n                                changes (default is 1 hour)\n        \"\"\"\n\n        self.feedurl = feedurl\n        self.branch = None\n        self.pollinterval = pollinterval\n        self.lastChange = None\n        self.loop = LoopingCall(self.poll)\n        self.src = None\n        for word in self.feedurl.split('/'):\n            if word == 'svnchanges':\n                self.src = 'svn'\n                break\n            elif word == 'hgchanges':\n                self.src = 'hg'\n                break\n            elif word == 'gitchanges':\n                self.src = 'git'\n                break\n\n    def startService(self):\n        log.msg(\"GoogleCodeAtomPoller starting\")\n        base.ChangeSource.startService(self)\n        reactor.callLater(0, self.loop.start, self.pollinterval)\n\n    def stopService(self):\n        log.msg(\"GoogleCodeAtomPoller stoppping\")\n        self.loop.stop()\n        return base.ChangeSource.stopService(self)\n\n    def describe(self):\n        return (\"Getting changes from the GoogleCode repo changes feed %s\" %\n               self._make_url())\n\n    def poll(self):\n        if self.working:\n            log.msg(\"Not polling because last poll is still working\")\n        else:\n            self.working = True\n            d = self._get_changes()\n            d.addCallback(self._process_changes)\n            d.addCallbacks(self._finished_ok, self._finished_failure)\n\n    def _finished_ok(self, res):\n        assert self.working\n        self.working = False\n        log.msg(\"GoogleCodeAtomPoller poll success\")\n\n        return res\n\n    def _finished_failure(self, res):\n        log.msg(\"GoogleCodeAtomPoller poll failed: %s\" % res)\n        assert self.working\n        self.working = False\n        return None\n\n    def _make_url(self):\n        return \"%s\" % (self.feedurl)\n\n    def _get_changes(self):\n        url = self._make_url()\n        log.msg(\"GoogleCodeAtomPoller polling %s\" % url)\n\n        return getPage(url, timeout=self.pollinterval)\n\n    def _parse_changes(self, query):\n        dom = minidom.parseString(query)\n        entries = dom.getElementsByTagName(\"entry\")\n        changes = []\n        # Entries come in reverse chronological order\n        for i in entries:\n            d = {}\n\n            # revision is the last part of the 'id' url\n            d[\"revision\"] = i.getElementsByTagName(\n                \"id\")[0].firstChild.data.split('/')[-1]\n            if d[\"revision\"] == self.lastChange:\n                break  # no more new changes\n\n            d[\"when\"] = timegm(strptime(\n                i.getElementsByTagName(\"updated\")[0].firstChild.data,\n                \"%Y-%m-%dT%H:%M:%SZ\"))\n            d[\"author\"] = i.getElementsByTagName(\n                \"author\")[0].getElementsByTagName(\"name\")[0].firstChild.data\n            # files and commit msg are separated by 2 consecutive <br/>\n            content = i.getElementsByTagName(\n                \"content\")[0].firstChild.data.split(\"<br/>\\n <br/>\")\n            # Remove the action keywords from the file list\n            fl = content[0].replace(\n                u' \\xa0\\xa0\\xa0\\xa0Add\\xa0\\xa0\\xa0\\xa0', '').replace(\n                u' \\xa0\\xa0\\xa0\\xa0Delete\\xa0\\xa0\\xa0\\xa0', '').replace(\n                u' \\xa0\\xa0\\xa0\\xa0Modify\\xa0\\xa0\\xa0\\xa0', '')\n            # Get individual files and remove the 'header'\n            d[\"files\"] = fl.encode(\"ascii\", \"replace\").split(\"<br/>\")[1:]\n            d[\"files\"] = [f.strip() for f in d[\"files\"]]\n            try:\n                d[\"comments\"] = content[1].encode(\"ascii\", \"replace\")\n            except:\n                d[\"comments\"] = \"No commit message provided\"\n\n            changes.append(d)\n\n        changes.reverse() # want them in chronological order\n        return changes\n\n    def _process_changes(self, query):\n        change_list = self._parse_changes(query)\n\n        # Skip calling addChange() if this is the first successful poll.\n        if self.lastChange is not None:\n            for change in change_list:\n                c = changes.Change(revision = change[\"revision\"],\n                                   who = change[\"author\"],\n                                   files = change[\"files\"],\n                                   comments = change[\"comments\"],\n                                   when = change[\"when\"],\n                                   branch = self.branch)\n                self.parent.addChange(c, src=self.src)\n        if change_list:\n            self.lastChange = change_list[-1][\"revision\"]\n", "path": "master/contrib/googlecode_atom.py"}], "after_files": [{"content": "# GoogleCode Atom Feed Poller\n# Author: Srivats P. <pstavirs>\n# Based on Mozilla's HgPoller\n#     http://bonsai.mozilla.org/cvsblame.cgi?file=/mozilla/tools/buildbot/buildbot/changes/Attic/hgpoller.py&revision=1.1.4.2\n#\n# Description:\n#   Use this ChangeSource for projects hosted on http://code.google.com/\n#\n#   This ChangeSource uses the project's commit Atom feed. Depending upon the\n#   frequency of commits, you can tune the polling interval for the feed\n#   (default is 1 hour)\n#\n# Parameters:\n#   feedurl (MANDATORY): The Atom feed URL of the GoogleCode repo\n#   pollinterval (OPTIONAL): Polling frequency for the feed (in seconds)\n#\n# Example:\n# To poll the Ostinato project's commit feed every 3 hours, use -\n#   from googlecode_atom import GoogleCodeAtomPoller\n#   poller = GoogleCodeAtomPoller(\n#            feedurl=\"http://code.google.com/feeds/p/ostinato/hgchanges/basic\",\n#            pollinterval=10800)\n#   c['change_source'] = [ poller ]\n#\n\nimport datetime\nfrom xml.dom import minidom, Node\n\nfrom twisted.python import log, failure\nfrom twisted.internet import defer, reactor\nfrom twisted.internet.task import LoopingCall\nfrom twisted.web.client import getPage\n\nfrom buildbot.changes import base\n\n\ndef googleCodePollerForProject(project, vcs, pollinterval=3600):\n    return GoogleCodeAtomPoller(\n        'http://code.google.com/feeds/p/%s/%schanges/basic' % (project, vcs),\n        pollinterval=pollinterval)\n\n\nclass GoogleCodeAtomPoller(base.ChangeSource):\n    \"\"\"This source will poll a GoogleCode Atom feed for changes and\n    submit them to the change master. Works for both Svn, Git, and Hg\n    repos.\n    TODO: branch processing\n    \"\"\"\n\n    compare_attrs = ['feedurl', 'pollinterval']\n    parent = None\n    loop = None\n    volatile = ['loop']\n    working = False\n\n    def __init__(self, feedurl, pollinterval=3600):\n        \"\"\"\n        @type   feedurl:        string\n        @param  feedurl:        The Atom feed URL of the GoogleCode repo\n                                (e.g. http://code.google.com/feeds/p/ostinato/hgchanges/basic)\n\n        @type   pollinterval:   int\n        @param  pollinterval:   The time (in seconds) between queries for\n                                changes (default is 1 hour)\n        \"\"\"\n\n        self.feedurl = feedurl\n        self.branch = None\n        self.pollinterval = pollinterval\n        self.lastChange = None\n        self.loop = LoopingCall(self.poll)\n        self.src = None\n        for word in self.feedurl.split('/'):\n            if word == 'svnchanges':\n                self.src = 'svn'\n                break\n            elif word == 'hgchanges':\n                self.src = 'hg'\n                break\n            elif word == 'gitchanges':\n                self.src = 'git'\n                break\n\n    def startService(self):\n        log.msg(\"GoogleCodeAtomPoller starting\")\n        base.ChangeSource.startService(self)\n        reactor.callLater(0, self.loop.start, self.pollinterval)\n\n    def stopService(self):\n        log.msg(\"GoogleCodeAtomPoller stoppping\")\n        self.loop.stop()\n        return base.ChangeSource.stopService(self)\n\n    def describe(self):\n        return (\"Getting changes from the GoogleCode repo changes feed %s\" %\n               self._make_url())\n\n    def poll(self):\n        if self.working:\n            log.msg(\"Not polling because last poll is still working\")\n        else:\n            self.working = True\n            d = self._get_changes()\n            d.addCallback(self._process_changes)\n            d.addCallbacks(self._finished_ok, self._finished_failure)\n\n    def _finished_ok(self, res):\n        assert self.working\n        self.working = False\n        log.msg(\"GoogleCodeAtomPoller poll success\")\n\n        return res\n\n    def _finished_failure(self, res):\n        log.msg(\"GoogleCodeAtomPoller poll failed: %s\" % res)\n        assert self.working\n        self.working = False\n        return None\n\n    def _make_url(self):\n        return \"%s\" % (self.feedurl)\n\n    def _get_changes(self):\n        url = self._make_url()\n        log.msg(\"GoogleCodeAtomPoller polling %s\" % url)\n\n        return getPage(url, timeout=self.pollinterval)\n\n    def _parse_changes(self, query):\n        dom = minidom.parseString(query)\n        entries = dom.getElementsByTagName(\"entry\")\n        changes = []\n        # Entries come in reverse chronological order\n        for i in entries:\n            d = {}\n\n            # revision is the last part of the 'id' url\n            d[\"revision\"] = i.getElementsByTagName(\n                \"id\")[0].firstChild.data.split('/')[-1]\n            if d[\"revision\"] == self.lastChange:\n                break  # no more new changes\n\n            d[\"when\"] = datetime.datetime.strptime(\n                i.getElementsByTagName(\"updated\")[0].firstChild.data,\n                \"%Y-%m-%dT%H:%M:%SZ\")\n            d[\"author\"] = i.getElementsByTagName(\n                \"author\")[0].getElementsByTagName(\"name\")[0].firstChild.data\n            # files and commit msg are separated by 2 consecutive <br/>\n            content = i.getElementsByTagName(\n                \"content\")[0].firstChild.data.split(\"<br/>\\n <br/>\")\n            # Remove the action keywords from the file list\n            fl = content[0].replace(\n                u' \\xa0\\xa0\\xa0\\xa0Add\\xa0\\xa0\\xa0\\xa0', '').replace(\n                u' \\xa0\\xa0\\xa0\\xa0Delete\\xa0\\xa0\\xa0\\xa0', '').replace(\n                u' \\xa0\\xa0\\xa0\\xa0Modify\\xa0\\xa0\\xa0\\xa0', '')\n            # Get individual files and remove the 'header'\n            d[\"files\"] = fl.encode(\"ascii\", \"replace\").split(\"<br/>\")[1:]\n            d[\"files\"] = [f.strip() for f in d[\"files\"]]\n            try:\n                d[\"comments\"] = content[1].encode(\"ascii\", \"replace\")\n            except:\n                d[\"comments\"] = \"No commit message provided\"\n\n            changes.append(d)\n\n        changes.reverse() # want them in chronological order\n        return changes\n\n    @defer.deferredGenerator\n    def _process_changes(self, query):\n        change_list = self._parse_changes(query)\n\n        # Skip calling addChange() if this is the first successful poll.\n        if self.lastChange is not None:\n            for change in change_list:\n                d = self.master.addChange(author=change[\"author\"],\n                                          revision=change[\"revision\"],\n                                          files=change[\"files\"],\n                                          comments=change[\"comments\"],\n                                          when_timestamp=change[\"when\"],\n                                          branch=self.branch,\n                                          src=self.src)\n                wfd = defer.waitForDeferred(d)\n                yield wfd\n                results = wfd.getResult()\n        if change_list:\n            self.lastChange = change_list[-1][\"revision\"]\n", "path": "master/contrib/googlecode_atom.py"}]}