We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add a backport of `SynchronousTestCasa`
This actually just makes `TestCase` pretend to be `SynchronousTestCase` currently, since the difference is mostly just that `SynchronousTestCase` does less. (There is also some stuff that was add to `SynchronousTestCase` that makes synchronous testing easier, but on versions with that code `TestCase` inherits from it).

This incidentally bumps the minimum version of twisted required for the worker to 10.2.0, which is 5y 12mo old, and is the old version that we tested against that supports deferred cancellation, which was used in #2464. (It was introduced in 10.1.0, bu that that wasn't in our test matrix, and 10.2.0 is plenty old enough).


--- 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/buildbot/util/maildir.py`
Content:
```
1 # This file is part of Buildbot.  Buildbot is free software: you can
2 # redistribute it and/or modify it under the terms of the GNU General Public
3 # License as published by the Free Software Foundation, version 2.
4 #
5 # This program is distributed in the hope that it will be useful, but WITHOUT
6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
8 # details.
9 #
10 # You should have received a copy of the GNU General Public License along with
11 # this program; if not, write to the Free Software Foundation, Inc., 51
12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
13 #
14 # Copyright Buildbot Team Members
15 
16 
17 # This is a class which watches a maildir for new messages. It uses the
18 # linux dirwatcher API (if available) to look for new files. The
19 # .messageReceived method is invoked with the filename of the new message,
20 # relative to the top of the maildir (so it will look like "new/blahblah").
21 
22 import os
23 from twisted.python import log, runtime
24 from twisted.application import service, internet
25 from twisted.internet import reactor, defer
26 dnotify = None
27 try:
28     import dnotify
29 except:
30     log.msg("unable to import dnotify, so Maildir will use polling instead")
31 
32 class NoSuchMaildir(Exception):
33     pass
34 
35 class MaildirService(service.MultiService):
36     pollinterval = 10  # only used if we don't have DNotify
37 
38     def __init__(self, basedir=None):
39         service.MultiService.__init__(self)
40         if basedir:
41             self.setBasedir(basedir)
42         self.files = []
43         self.dnotify = None
44 
45     def setBasedir(self, basedir):
46         # some users of MaildirService (scheduler.Try_Jobdir, in particular)
47         # don't know their basedir until setServiceParent, since it is
48         # relative to the buildmaster's basedir. So let them set it late. We
49         # don't actually need it until our own startService.
50         self.basedir = basedir
51         self.newdir = os.path.join(self.basedir, "new")
52         self.curdir = os.path.join(self.basedir, "cur")
53 
54     def startService(self):
55         service.MultiService.startService(self)
56         if not os.path.isdir(self.newdir) or not os.path.isdir(self.curdir):
57             raise NoSuchMaildir("invalid maildir '%s'" % self.basedir)
58         try:
59             if dnotify:
60                 # we must hold an fd open on the directory, so we can get
61                 # notified when it changes.
62                 self.dnotify = dnotify.DNotify(self.newdir,
63                                                self.dnotify_callback,
64                                                [dnotify.DNotify.DN_CREATE])
65         except (IOError, OverflowError):
66             # IOError is probably linux<2.4.19, which doesn't support
67             # dnotify. OverflowError will occur on some 64-bit machines
68             # because of a python bug
69             log.msg("DNotify failed, falling back to polling")
70         if not self.dnotify:
71             t = internet.TimerService(self.pollinterval, self.poll)
72             t.setServiceParent(self)
73         self.poll()
74 
75     def dnotify_callback(self):
76         log.msg("dnotify noticed something, now polling")
77 
78         # give it a moment. I found that qmail had problems when the message
79         # was removed from the maildir instantly. It shouldn't, that's what
80         # maildirs are made for. I wasn't able to eyeball any reason for the
81         # problem, and safecat didn't behave the same way, but qmail reports
82         # "Temporary_error_on_maildir_delivery" (qmail-local.c:165,
83         # maildir_child() process exited with rc not in 0,2,3,4). Not sure
84         # why, and I'd have to hack qmail to investigate further, so it's
85         # easier to just wait a second before yanking the message out of new/
86 
87         reactor.callLater(0.1, self.poll)
88 
89 
90     def stopService(self):
91         if self.dnotify:
92             self.dnotify.remove()
93             self.dnotify = None
94         return service.MultiService.stopService(self)
95 
96     @defer.inlineCallbacks
97     def poll(self):
98         try:
99             assert self.basedir
100             # see what's new
101             for f in self.files:
102                 if not os.path.isfile(os.path.join(self.newdir, f)):
103                     self.files.remove(f)
104             newfiles = []
105             for f in os.listdir(self.newdir):
106                 if not f in self.files:
107                     newfiles.append(f)
108             self.files.extend(newfiles)
109             for n in newfiles:
110                 try:
111                     yield self.messageReceived(n)
112                 except:
113                     log.err(None, "while reading '%s' from maildir '%s':" % (n, self.basedir))
114         except Exception:
115             log.err(None, "while polling maildir '%s':" % (self.basedir,))
116 
117     def moveToCurDir(self, filename):
118         if runtime.platformType == "posix":
119             # open the file before moving it, because I'm afraid that once
120             # it's in cur/, someone might delete it at any moment
121             path = os.path.join(self.newdir, filename)
122             f = open(path, "r")
123             os.rename(os.path.join(self.newdir, filename),
124                       os.path.join(self.curdir, filename))
125         elif runtime.platformType == "win32":
126             # do this backwards under windows, because you can't move a file
127             # that somebody is holding open. This was causing a Permission
128             # Denied error on bear's win32-twisted1.3 buildslave.
129             os.rename(os.path.join(self.newdir, filename),
130                       os.path.join(self.curdir, filename))
131             path = os.path.join(self.curdir, filename)
132             f = open(path, "r")
133 
134         return f
135 
136     def messageReceived(self, filename):
137         raise NotImplementedError
138
```
--- 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/buildbot/util/maildir.py b/master/buildbot/util/maildir.py
--- a/master/buildbot/util/maildir.py
+++ b/master/buildbot/util/maildir.py
@@ -41,6 +41,7 @@
             self.setBasedir(basedir)
         self.files = []
         self.dnotify = None
+        self.timerService = None
 
     def setBasedir(self, basedir):
         # some users of MaildirService (scheduler.Try_Jobdir, in particular)
@@ -68,10 +69,11 @@
             # because of a python bug
             log.msg("DNotify failed, falling back to polling")
         if not self.dnotify:
-            t = internet.TimerService(self.pollinterval, self.poll)
-            t.setServiceParent(self)
-        self.poll()
-
+            self.timerService = internet.TimerService(self.pollinterval, self.poll)
+            self.timerService.setServiceParent(self)
+        self.poll()  
+           
+        
     def dnotify_callback(self):
         log.msg("dnotify noticed something, now polling")
 
@@ -91,6 +93,9 @@
         if self.dnotify:
             self.dnotify.remove()
             self.dnotify = None
+        if self.timerService is not None:
+            self.timerService.disownServiceParent() 
+            self.timerService = None
         return service.MultiService.stopService(self)
 
     @defer.inlineCallbacks

{"golden_diff": "diff --git a/master/buildbot/util/maildir.py b/master/buildbot/util/maildir.py\n--- a/master/buildbot/util/maildir.py\n+++ b/master/buildbot/util/maildir.py\n@@ -41,6 +41,7 @@\n             self.setBasedir(basedir)\n         self.files = []\n         self.dnotify = None\n+        self.timerService = None\n \n     def setBasedir(self, basedir):\n         # some users of MaildirService (scheduler.Try_Jobdir, in particular)\n@@ -68,10 +69,11 @@\n             # because of a python bug\n             log.msg(\"DNotify failed, falling back to polling\")\n         if not self.dnotify:\n-            t = internet.TimerService(self.pollinterval, self.poll)\n-            t.setServiceParent(self)\n-        self.poll()\n-\n+            self.timerService = internet.TimerService(self.pollinterval, self.poll)\n+            self.timerService.setServiceParent(self)\n+        self.poll()  \n+           \n+        \n     def dnotify_callback(self):\n         log.msg(\"dnotify noticed something, now polling\")\n \n@@ -91,6 +93,9 @@\n         if self.dnotify:\n             self.dnotify.remove()\n             self.dnotify = None\n+        if self.timerService is not None:\n+            self.timerService.disownServiceParent() \n+            self.timerService = None\n         return service.MultiService.stopService(self)\n \n     @defer.inlineCallbacks\n", "issue": "Add a backport of `SynchronousTestCasa`\nThis actually just makes `TestCase` pretend to be `SynchronousTestCase` currently, since the difference is mostly just that `SynchronousTestCase` does less. (There is also some stuff that was add to `SynchronousTestCase` that makes synchronous testing easier, but on versions with that code `TestCase` inherits from it).\n\nThis incidentally bumps the minimum version of twisted required for the worker to 10.2.0, which is 5y 12mo old, and is the old version that we tested against that supports deferred cancellation, which was used in #2464. (It was introduced in 10.1.0, bu that that wasn't in our test matrix, and 10.2.0 is plenty old enough).\n\n", "before_files": [{"content": "# This file is part of Buildbot.  Buildbot is free software: you can\n# redistribute it and/or modify it under the terms of the GNU General Public\n# License as published by the Free Software Foundation, version 2.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT\n# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program; if not, write to the Free Software Foundation, Inc., 51\n# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n#\n# Copyright Buildbot Team Members\n\n\n# This is a class which watches a maildir for new messages. It uses the\n# linux dirwatcher API (if available) to look for new files. The\n# .messageReceived method is invoked with the filename of the new message,\n# relative to the top of the maildir (so it will look like \"new/blahblah\").\n\nimport os\nfrom twisted.python import log, runtime\nfrom twisted.application import service, internet\nfrom twisted.internet import reactor, defer\ndnotify = None\ntry:\n    import dnotify\nexcept:\n    log.msg(\"unable to import dnotify, so Maildir will use polling instead\")\n\nclass NoSuchMaildir(Exception):\n    pass\n\nclass MaildirService(service.MultiService):\n    pollinterval = 10  # only used if we don't have DNotify\n\n    def __init__(self, basedir=None):\n        service.MultiService.__init__(self)\n        if basedir:\n            self.setBasedir(basedir)\n        self.files = []\n        self.dnotify = None\n\n    def setBasedir(self, basedir):\n        # some users of MaildirService (scheduler.Try_Jobdir, in particular)\n        # don't know their basedir until setServiceParent, since it is\n        # relative to the buildmaster's basedir. So let them set it late. We\n        # don't actually need it until our own startService.\n        self.basedir = basedir\n        self.newdir = os.path.join(self.basedir, \"new\")\n        self.curdir = os.path.join(self.basedir, \"cur\")\n\n    def startService(self):\n        service.MultiService.startService(self)\n        if not os.path.isdir(self.newdir) or not os.path.isdir(self.curdir):\n            raise NoSuchMaildir(\"invalid maildir '%s'\" % self.basedir)\n        try:\n            if dnotify:\n                # we must hold an fd open on the directory, so we can get\n                # notified when it changes.\n                self.dnotify = dnotify.DNotify(self.newdir,\n                                               self.dnotify_callback,\n                                               [dnotify.DNotify.DN_CREATE])\n        except (IOError, OverflowError):\n            # IOError is probably linux<2.4.19, which doesn't support\n            # dnotify. OverflowError will occur on some 64-bit machines\n            # because of a python bug\n            log.msg(\"DNotify failed, falling back to polling\")\n        if not self.dnotify:\n            t = internet.TimerService(self.pollinterval, self.poll)\n            t.setServiceParent(self)\n        self.poll()\n\n    def dnotify_callback(self):\n        log.msg(\"dnotify noticed something, now polling\")\n\n        # give it a moment. I found that qmail had problems when the message\n        # was removed from the maildir instantly. It shouldn't, that's what\n        # maildirs are made for. I wasn't able to eyeball any reason for the\n        # problem, and safecat didn't behave the same way, but qmail reports\n        # \"Temporary_error_on_maildir_delivery\" (qmail-local.c:165,\n        # maildir_child() process exited with rc not in 0,2,3,4). Not sure\n        # why, and I'd have to hack qmail to investigate further, so it's\n        # easier to just wait a second before yanking the message out of new/\n\n        reactor.callLater(0.1, self.poll)\n\n\n    def stopService(self):\n        if self.dnotify:\n            self.dnotify.remove()\n            self.dnotify = None\n        return service.MultiService.stopService(self)\n\n    @defer.inlineCallbacks\n    def poll(self):\n        try:\n            assert self.basedir\n            # see what's new\n            for f in self.files:\n                if not os.path.isfile(os.path.join(self.newdir, f)):\n                    self.files.remove(f)\n            newfiles = []\n            for f in os.listdir(self.newdir):\n                if not f in self.files:\n                    newfiles.append(f)\n            self.files.extend(newfiles)\n            for n in newfiles:\n                try:\n                    yield self.messageReceived(n)\n                except:\n                    log.err(None, \"while reading '%s' from maildir '%s':\" % (n, self.basedir))\n        except Exception:\n            log.err(None, \"while polling maildir '%s':\" % (self.basedir,))\n\n    def moveToCurDir(self, filename):\n        if runtime.platformType == \"posix\":\n            # open the file before moving it, because I'm afraid that once\n            # it's in cur/, someone might delete it at any moment\n            path = os.path.join(self.newdir, filename)\n            f = open(path, \"r\")\n            os.rename(os.path.join(self.newdir, filename),\n                      os.path.join(self.curdir, filename))\n        elif runtime.platformType == \"win32\":\n            # do this backwards under windows, because you can't move a file\n            # that somebody is holding open. This was causing a Permission\n            # Denied error on bear's win32-twisted1.3 buildslave.\n            os.rename(os.path.join(self.newdir, filename),\n                      os.path.join(self.curdir, filename))\n            path = os.path.join(self.curdir, filename)\n            f = open(path, \"r\")\n\n        return f\n\n    def messageReceived(self, filename):\n        raise NotImplementedError\n", "path": "master/buildbot/util/maildir.py"}], "after_files": [{"content": "# This file is part of Buildbot.  Buildbot is free software: you can\n# redistribute it and/or modify it under the terms of the GNU General Public\n# License as published by the Free Software Foundation, version 2.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT\n# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program; if not, write to the Free Software Foundation, Inc., 51\n# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n#\n# Copyright Buildbot Team Members\n\n\n# This is a class which watches a maildir for new messages. It uses the\n# linux dirwatcher API (if available) to look for new files. The\n# .messageReceived method is invoked with the filename of the new message,\n# relative to the top of the maildir (so it will look like \"new/blahblah\").\n\nimport os\nfrom twisted.python import log, runtime\nfrom twisted.application import service, internet\nfrom twisted.internet import reactor, defer\ndnotify = None\ntry:\n    import dnotify\nexcept:\n    log.msg(\"unable to import dnotify, so Maildir will use polling instead\")\n\nclass NoSuchMaildir(Exception):\n    pass\n\nclass MaildirService(service.MultiService):\n    pollinterval = 10  # only used if we don't have DNotify\n\n    def __init__(self, basedir=None):\n        service.MultiService.__init__(self)\n        if basedir:\n            self.setBasedir(basedir)\n        self.files = []\n        self.dnotify = None\n        self.timerService = None\n\n    def setBasedir(self, basedir):\n        # some users of MaildirService (scheduler.Try_Jobdir, in particular)\n        # don't know their basedir until setServiceParent, since it is\n        # relative to the buildmaster's basedir. So let them set it late. We\n        # don't actually need it until our own startService.\n        self.basedir = basedir\n        self.newdir = os.path.join(self.basedir, \"new\")\n        self.curdir = os.path.join(self.basedir, \"cur\")\n\n    def startService(self):\n        service.MultiService.startService(self)\n        if not os.path.isdir(self.newdir) or not os.path.isdir(self.curdir):\n            raise NoSuchMaildir(\"invalid maildir '%s'\" % self.basedir)\n        try:\n            if dnotify:\n                # we must hold an fd open on the directory, so we can get\n                # notified when it changes.\n                self.dnotify = dnotify.DNotify(self.newdir,\n                                               self.dnotify_callback,\n                                               [dnotify.DNotify.DN_CREATE])\n        except (IOError, OverflowError):\n            # IOError is probably linux<2.4.19, which doesn't support\n            # dnotify. OverflowError will occur on some 64-bit machines\n            # because of a python bug\n            log.msg(\"DNotify failed, falling back to polling\")\n        if not self.dnotify:\n            self.timerService = internet.TimerService(self.pollinterval, self.poll)\n            self.timerService.setServiceParent(self)\n        self.poll()  \n           \n        \n    def dnotify_callback(self):\n        log.msg(\"dnotify noticed something, now polling\")\n\n        # give it a moment. I found that qmail had problems when the message\n        # was removed from the maildir instantly. It shouldn't, that's what\n        # maildirs are made for. I wasn't able to eyeball any reason for the\n        # problem, and safecat didn't behave the same way, but qmail reports\n        # \"Temporary_error_on_maildir_delivery\" (qmail-local.c:165,\n        # maildir_child() process exited with rc not in 0,2,3,4). Not sure\n        # why, and I'd have to hack qmail to investigate further, so it's\n        # easier to just wait a second before yanking the message out of new/\n\n        reactor.callLater(0.1, self.poll)\n\n\n    def stopService(self):\n        if self.dnotify:\n            self.dnotify.remove()\n            self.dnotify = None\n        if self.timerService is not None:\n            self.timerService.disownServiceParent() \n            self.timerService = None\n        return service.MultiService.stopService(self)\n\n    @defer.inlineCallbacks\n    def poll(self):\n        try:\n            assert self.basedir\n            # see what's new\n            for f in self.files:\n                if not os.path.isfile(os.path.join(self.newdir, f)):\n                    self.files.remove(f)\n            newfiles = []\n            for f in os.listdir(self.newdir):\n                if not f in self.files:\n                    newfiles.append(f)\n            self.files.extend(newfiles)\n            for n in newfiles:\n                try:\n                    yield self.messageReceived(n)\n                except:\n                    log.err(None, \"while reading '%s' from maildir '%s':\" % (n, self.basedir))\n        except Exception:\n            log.err(None, \"while polling maildir '%s':\" % (self.basedir,))\n\n    def moveToCurDir(self, filename):\n        if runtime.platformType == \"posix\":\n            # open the file before moving it, because I'm afraid that once\n            # it's in cur/, someone might delete it at any moment\n            path = os.path.join(self.newdir, filename)\n            f = open(path, \"r\")\n            os.rename(os.path.join(self.newdir, filename),\n                      os.path.join(self.curdir, filename))\n        elif runtime.platformType == \"win32\":\n            # do this backwards under windows, because you can't move a file\n            # that somebody is holding open. This was causing a Permission\n            # Denied error on bear's win32-twisted1.3 buildslave.\n            os.rename(os.path.join(self.newdir, filename),\n                      os.path.join(self.curdir, filename))\n            path = os.path.join(self.curdir, filename)\n            f = open(path, \"r\")\n\n        return f\n\n    def messageReceived(self, filename):\n        raise NotImplementedError\n", "path": "master/buildbot/util/maildir.py"}]}