We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Scheduled weekly dependency update for week 28



## Updates
Here's a list of all the updates bundled in this pull request. I've added some links to make it easier for you to find all the information you need.
<table align="center">

<tr>
<td><b>boto</b></td>
<td align="center">2.47.0</td>
<td align="center">&raquo;</td>
<td align="center">2.48.0</td>
<td>
     <a href="https://pypi.python.org/pypi/boto">PyPI</a> | <a href="https://pyup.io/changelogs/boto/">Changelog</a> | <a href="https://github.com/boto/boto/">Repo</a> 

</td>

<tr>
<td><b>botocore</b></td>
<td align="center">1.5.78</td>
<td align="center">&raquo;</td>
<td align="center">1.5.80</td>
<td>
     <a href="https://pypi.python.org/pypi/botocore">PyPI</a> | <a href="https://pyup.io/changelogs/botocore/">Changelog</a> | <a href="https://github.com/boto/botocore">Repo</a> 

</td>

<tr>
<td><b>Pillow</b></td>
<td align="center">4.2.0</td>
<td align="center">&raquo;</td>
<td align="center">4.2.1</td>
<td>
     <a href="https://pypi.python.org/pypi/pillow">PyPI</a> | <a href="https://pyup.io/changelogs/pillow/">Changelog</a> | <a href="https://python-pillow.org">Homepage</a> 

</td>

<tr>
<td><b>pycparser</b></td>
<td align="center">2.17</td>
<td align="center">&raquo;</td>
<td align="center">2.18</td>
<td>
     <a href="https://pypi.python.org/pypi/pycparser">PyPI</a> | <a href="https://pyup.io/changelogs/pycparser/">Changelog</a> | <a href="https://github.com/eliben/pycparser">Repo</a> 

</td>

<tr>
<td><b>buildbot-www</b></td>
<td align="center">0.9.9.post1</td>
<td align="center">&raquo;</td>
<td align="center">0.9.9.post2</td>
<td>
     <a href="https://pypi.python.org/pypi/buildbot-www">PyPI</a> | <a href="http://buildbot.net/">Homepage</a> 

</td>

</tr>
</table>



## Changelogs


### boto 2.47.0 -> 2.48.0

>### 2.48.0

>============

>:date: 2017/06/29

>This release addresses a few S3 related bugs as well as a bug with the recent
>endpoint heuristics feature.

>Changes
>-------
>* Fix generate_url() AttributeError when using anonymous connections (:issue:`3734`, :sha:`83481807`)
>* Use RegionInfo by default with heuristics (:issue:`3737`, :sha:`0a9b1140`)
>* Allow specifying s3 host from boto config file. (:issue:`3738`, :sha:`dcfc7512`)










### botocore 1.5.78 -> 1.5.80

>### 1.5.80

>======

>* api-change:``kinesis``: Update kinesis client to latest version
>* api-change:``kms``: Update kms client to latest version
>* api-change:``ds``: Update ds client to latest version
>* api-change:``ssm``: Update ssm client to latest version




>### 1.5.79

>======

>* api-change:``cloudwatch``: Update cloudwatch client to latest version
>* api-change:``route53``: Update route53 client to latest version








### Pillow 4.2.0 -> 4.2.1

>### 4.2.1

>------------------

>- CI: Fix version specification and test on CI for PyPy/Windows 2608
>  [wiredfool]







### pycparser 2.17 -> 2.18

>### 2.18


>  - PR 161 &amp; 184: Update bundled PLY version to 3.10
>  - PR 158: Add support for the __int128 type.
>  - PR 169: Handle more tricky TYPEID in declarators.
>  - PR 178: Add columns to the coord of each node










That's it for now!

Happy merging! 🤖


--- 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/data/forceschedulers.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 from twisted.internet import defer
17 
18 from buildbot.data import base
19 from buildbot.data import types
20 from buildbot.schedulers import forcesched
21 from buildbot.www.rest import JSONRPC_CODES
22 from buildbot.www.rest import BadJsonRpc2
23 
24 
25 def forceScheduler2Data(sched):
26     ret = dict(all_fields=[],
27                name=unicode(sched.name),
28                button_name=unicode(sched.buttonName),
29                label=unicode(sched.label),
30                builder_names=map(unicode, sched.builderNames))
31     ret["all_fields"] = [field.getSpec() for field in sched.all_fields]
32     return ret
33 
34 
35 class ForceSchedulerEndpoint(base.Endpoint):
36 
37     isCollection = False
38     pathPatterns = """
39         /forceschedulers/i:schedulername
40     """
41 
42     def findForceScheduler(self, schedulername):
43         # eventually this may be db backed. This is why the API is async
44         for sched in self.master.allSchedulers():
45             if sched.name == schedulername and isinstance(sched, forcesched.ForceScheduler):
46                 return defer.succeed(sched)
47 
48     @defer.inlineCallbacks
49     def get(self, resultSpec, kwargs):
50         sched = yield self.findForceScheduler(kwargs['schedulername'])
51         if sched is not None:
52             defer.returnValue(forceScheduler2Data(sched))
53 
54     @defer.inlineCallbacks
55     def control(self, action, args, kwargs):
56         if action == "force":
57             sched = yield self.findForceScheduler(kwargs['schedulername'])
58             if "owner" not in args:
59                 args['owner'] = "user"
60             try:
61                 res = yield sched.force(**args)
62                 defer.returnValue(res)
63             except forcesched.CollectedValidationError as e:
64                 raise BadJsonRpc2(e.errors, JSONRPC_CODES["invalid_params"])
65         defer.returnValue(None)
66 
67 
68 class ForceSchedulersEndpoint(base.Endpoint):
69 
70     isCollection = True
71     pathPatterns = """
72         /forceschedulers
73         /builders/:builderid/forceschedulers
74     """
75     rootLinkName = 'forceschedulers'
76 
77     @defer.inlineCallbacks
78     def get(self, resultSpec, kwargs):
79         l = []
80         builderid = kwargs.get('builderid', None)
81         if builderid is not None:
82             bdict = yield self.master.db.builders.getBuilder(builderid)
83         for sched in self.master.allSchedulers():
84             if isinstance(sched, forcesched.ForceScheduler):
85                 if builderid is not None and bdict['name'] not in sched.builderNames:
86                     continue
87                 l.append(forceScheduler2Data(sched))
88         defer.returnValue(l)
89 
90 
91 class ForceScheduler(base.ResourceType):
92 
93     name = "forcescheduler"
94     plural = "forceschedulers"
95     endpoints = [ForceSchedulerEndpoint, ForceSchedulersEndpoint]
96     keyFields = []
97 
98     class EntityType(types.Entity):
99         name = types.Identifier(20)
100         button_name = types.String()
101         label = types.String()
102         builder_names = types.List(of=types.Identifier(20))
103         all_fields = types.List(of=types.JsonObject())
104     entityType = EntityType(name)
105
```

Path: `master/buildbot/data/builders.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 from twisted.internet import defer
17 
18 from buildbot.data import base
19 from buildbot.data import types
20 
21 
22 class BuilderEndpoint(base.Endpoint):
23 
24     isCollection = False
25     pathPatterns = """
26         /builders/n:builderid
27         /masters/n:masterid/builders/n:builderid
28     """
29 
30     @defer.inlineCallbacks
31     def get(self, resultSpec, kwargs):
32         builderid = kwargs['builderid']
33         bdict = yield self.master.db.builders.getBuilder(builderid)
34         if not bdict:
35             defer.returnValue(None)
36             return
37         if 'masterid' in kwargs:
38             if kwargs['masterid'] not in bdict['masterids']:
39                 defer.returnValue(None)
40                 return
41         defer.returnValue(
42             dict(builderid=builderid,
43                  name=bdict['name'],
44                  masterids=bdict['masterids'],
45                  description=bdict['description'],
46                  tags=bdict['tags']))
47 
48 
49 class BuildersEndpoint(base.Endpoint):
50 
51     isCollection = True
52     rootLinkName = 'builders'
53     pathPatterns = """
54         /builders
55         /masters/n:masterid/builders
56     """
57 
58     @defer.inlineCallbacks
59     def get(self, resultSpec, kwargs):
60         bdicts = yield self.master.db.builders.getBuilders(
61             masterid=kwargs.get('masterid', None))
62         defer.returnValue([
63             dict(builderid=bd['id'],
64                  name=bd['name'],
65                  masterids=bd['masterids'],
66                  description=bd['description'],
67                  tags=bd['tags'])
68             for bd in bdicts])
69 
70 
71 class Builder(base.ResourceType):
72 
73     name = "builder"
74     plural = "builders"
75     endpoints = [BuilderEndpoint, BuildersEndpoint]
76     keyFields = ['builderid']
77 
78     class EntityType(types.Entity):
79         builderid = types.Integer()
80         name = types.Identifier(20)
81         masterids = types.List(of=types.Integer())
82         description = types.NoneOk(types.String())
83         tags = types.List(of=types.String())
84     entityType = EntityType(name)
85 
86     def __init__(self, master):
87         base.ResourceType.__init__(self, master)
88 
89     @base.updateMethod
90     def findBuilderId(self, name):
91         return self.master.db.builders.findBuilderId(name)
92 
93     @base.updateMethod
94     def updateBuilderInfo(self, builderid, description, tags):
95         return self.master.db.builders.updateBuilderInfo(builderid, description, tags)
96 
97     @base.updateMethod
98     @defer.inlineCallbacks
99     def updateBuilderList(self, masterid, builderNames):
100         # get the "current" list of builders for this master, so we know what
101         # changes to make.  Race conditions here aren't a great worry, as this
102         # is the only master inserting or deleting these records.
103         builders = yield self.master.db.builders.getBuilders(masterid=masterid)
104 
105         # figure out what to remove and remove it
106         builderNames_set = set(builderNames)
107         for bldr in builders:
108             if bldr['name'] not in builderNames_set:
109                 builderid = bldr['id']
110                 yield self.master.db.builders.removeBuilderMaster(
111                     masterid=masterid, builderid=builderid)
112                 self.master.mq.produce(('builders', str(builderid), 'stopped'),
113                                        dict(builderid=builderid, masterid=masterid,
114                                             name=bldr['name']))
115             else:
116                 builderNames_set.remove(bldr['name'])
117 
118         # now whatever's left in builderNames_set is new
119         for name in builderNames_set:
120             builderid = yield self.master.db.builders.findBuilderId(name)
121             yield self.master.db.builders.addBuilderMaster(
122                 masterid=masterid, builderid=builderid)
123             self.master.mq.produce(('builders', str(builderid), 'started'),
124                                    dict(builderid=builderid, masterid=masterid, name=name))
125 
126     @defer.inlineCallbacks
127     def _masterDeactivated(self, masterid):
128         # called from the masters rtype to indicate that the given master is
129         # deactivated
130         yield self.updateBuilderList(masterid, [])
131
```
--- 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/data/builders.py b/master/buildbot/data/builders.py
--- a/master/buildbot/data/builders.py
+++ b/master/buildbot/data/builders.py
@@ -77,7 +77,7 @@
 
     class EntityType(types.Entity):
         builderid = types.Integer()
-        name = types.Identifier(20)
+        name = types.Identifier(50)
         masterids = types.List(of=types.Integer())
         description = types.NoneOk(types.String())
         tags = types.List(of=types.String())
diff --git a/master/buildbot/data/forceschedulers.py b/master/buildbot/data/forceschedulers.py
--- a/master/buildbot/data/forceschedulers.py
+++ b/master/buildbot/data/forceschedulers.py
@@ -96,9 +96,9 @@
     keyFields = []
 
     class EntityType(types.Entity):
-        name = types.Identifier(20)
+        name = types.Identifier(50)
         button_name = types.String()
         label = types.String()
-        builder_names = types.List(of=types.Identifier(20))
+        builder_names = types.List(of=types.Identifier(50))
         all_fields = types.List(of=types.JsonObject())
     entityType = EntityType(name)

{"golden_diff": "diff --git a/master/buildbot/data/builders.py b/master/buildbot/data/builders.py\n--- a/master/buildbot/data/builders.py\n+++ b/master/buildbot/data/builders.py\n@@ -77,7 +77,7 @@\n \n     class EntityType(types.Entity):\n         builderid = types.Integer()\n-        name = types.Identifier(20)\n+        name = types.Identifier(50)\n         masterids = types.List(of=types.Integer())\n         description = types.NoneOk(types.String())\n         tags = types.List(of=types.String())\ndiff --git a/master/buildbot/data/forceschedulers.py b/master/buildbot/data/forceschedulers.py\n--- a/master/buildbot/data/forceschedulers.py\n+++ b/master/buildbot/data/forceschedulers.py\n@@ -96,9 +96,9 @@\n     keyFields = []\n \n     class EntityType(types.Entity):\n-        name = types.Identifier(20)\n+        name = types.Identifier(50)\n         button_name = types.String()\n         label = types.String()\n-        builder_names = types.List(of=types.Identifier(20))\n+        builder_names = types.List(of=types.Identifier(50))\n         all_fields = types.List(of=types.JsonObject())\n     entityType = EntityType(name)\n", "issue": "Scheduled weekly dependency update for week 28\n\n\n\n## Updates\nHere's a list of all the updates bundled in this pull request. I've added some links to make it easier for you to find all the information you need.\n<table align=\"center\">\n\n<tr>\n<td><b>boto</b></td>\n<td align=\"center\">2.47.0</td>\n<td align=\"center\">&raquo;</td>\n<td align=\"center\">2.48.0</td>\n<td>\n     <a href=\"https://pypi.python.org/pypi/boto\">PyPI</a> | <a href=\"https://pyup.io/changelogs/boto/\">Changelog</a> | <a href=\"https://github.com/boto/boto/\">Repo</a> \n\n</td>\n\n<tr>\n<td><b>botocore</b></td>\n<td align=\"center\">1.5.78</td>\n<td align=\"center\">&raquo;</td>\n<td align=\"center\">1.5.80</td>\n<td>\n     <a href=\"https://pypi.python.org/pypi/botocore\">PyPI</a> | <a href=\"https://pyup.io/changelogs/botocore/\">Changelog</a> | <a href=\"https://github.com/boto/botocore\">Repo</a> \n\n</td>\n\n<tr>\n<td><b>Pillow</b></td>\n<td align=\"center\">4.2.0</td>\n<td align=\"center\">&raquo;</td>\n<td align=\"center\">4.2.1</td>\n<td>\n     <a href=\"https://pypi.python.org/pypi/pillow\">PyPI</a> | <a href=\"https://pyup.io/changelogs/pillow/\">Changelog</a> | <a href=\"https://python-pillow.org\">Homepage</a> \n\n</td>\n\n<tr>\n<td><b>pycparser</b></td>\n<td align=\"center\">2.17</td>\n<td align=\"center\">&raquo;</td>\n<td align=\"center\">2.18</td>\n<td>\n     <a href=\"https://pypi.python.org/pypi/pycparser\">PyPI</a> | <a href=\"https://pyup.io/changelogs/pycparser/\">Changelog</a> | <a href=\"https://github.com/eliben/pycparser\">Repo</a> \n\n</td>\n\n<tr>\n<td><b>buildbot-www</b></td>\n<td align=\"center\">0.9.9.post1</td>\n<td align=\"center\">&raquo;</td>\n<td align=\"center\">0.9.9.post2</td>\n<td>\n     <a href=\"https://pypi.python.org/pypi/buildbot-www\">PyPI</a> | <a href=\"http://buildbot.net/\">Homepage</a> \n\n</td>\n\n</tr>\n</table>\n\n\n\n## Changelogs\n\n\n### boto 2.47.0 -> 2.48.0\n\n>### 2.48.0\n\n>============\n\n>:date: 2017/06/29\n\n>This release addresses a few S3 related bugs as well as a bug with the recent\n>endpoint heuristics feature.\n\n>Changes\n>-------\n>* Fix generate_url() AttributeError when using anonymous connections (:issue:`3734`, :sha:`83481807`)\n>* Use RegionInfo by default with heuristics (:issue:`3737`, :sha:`0a9b1140`)\n>* Allow specifying s3 host from boto config file. (:issue:`3738`, :sha:`dcfc7512`)\n\n\n\n\n\n\n\n\n\n\n### botocore 1.5.78 -> 1.5.80\n\n>### 1.5.80\n\n>======\n\n>* api-change:``kinesis``: Update kinesis client to latest version\n>* api-change:``kms``: Update kms client to latest version\n>* api-change:``ds``: Update ds client to latest version\n>* api-change:``ssm``: Update ssm client to latest version\n\n\n\n\n>### 1.5.79\n\n>======\n\n>* api-change:``cloudwatch``: Update cloudwatch client to latest version\n>* api-change:``route53``: Update route53 client to latest version\n\n\n\n\n\n\n\n\n### Pillow 4.2.0 -> 4.2.1\n\n>### 4.2.1\n\n>------------------\n\n>- CI: Fix version specification and test on CI for PyPy/Windows 2608\n>  [wiredfool]\n\n\n\n\n\n\n\n### pycparser 2.17 -> 2.18\n\n>### 2.18\n\n\n>  - PR 161 &amp; 184: Update bundled PLY version to 3.10\n>  - PR 158: Add support for the __int128 type.\n>  - PR 169: Handle more tricky TYPEID in declarators.\n>  - PR 178: Add columns to the coord of each node\n\n\n\n\n\n\n\n\n\n\nThat's it for now!\n\nHappy merging! \ud83e\udd16\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\nfrom twisted.internet import defer\n\nfrom buildbot.data import base\nfrom buildbot.data import types\nfrom buildbot.schedulers import forcesched\nfrom buildbot.www.rest import JSONRPC_CODES\nfrom buildbot.www.rest import BadJsonRpc2\n\n\ndef forceScheduler2Data(sched):\n    ret = dict(all_fields=[],\n               name=unicode(sched.name),\n               button_name=unicode(sched.buttonName),\n               label=unicode(sched.label),\n               builder_names=map(unicode, sched.builderNames))\n    ret[\"all_fields\"] = [field.getSpec() for field in sched.all_fields]\n    return ret\n\n\nclass ForceSchedulerEndpoint(base.Endpoint):\n\n    isCollection = False\n    pathPatterns = \"\"\"\n        /forceschedulers/i:schedulername\n    \"\"\"\n\n    def findForceScheduler(self, schedulername):\n        # eventually this may be db backed. This is why the API is async\n        for sched in self.master.allSchedulers():\n            if sched.name == schedulername and isinstance(sched, forcesched.ForceScheduler):\n                return defer.succeed(sched)\n\n    @defer.inlineCallbacks\n    def get(self, resultSpec, kwargs):\n        sched = yield self.findForceScheduler(kwargs['schedulername'])\n        if sched is not None:\n            defer.returnValue(forceScheduler2Data(sched))\n\n    @defer.inlineCallbacks\n    def control(self, action, args, kwargs):\n        if action == \"force\":\n            sched = yield self.findForceScheduler(kwargs['schedulername'])\n            if \"owner\" not in args:\n                args['owner'] = \"user\"\n            try:\n                res = yield sched.force(**args)\n                defer.returnValue(res)\n            except forcesched.CollectedValidationError as e:\n                raise BadJsonRpc2(e.errors, JSONRPC_CODES[\"invalid_params\"])\n        defer.returnValue(None)\n\n\nclass ForceSchedulersEndpoint(base.Endpoint):\n\n    isCollection = True\n    pathPatterns = \"\"\"\n        /forceschedulers\n        /builders/:builderid/forceschedulers\n    \"\"\"\n    rootLinkName = 'forceschedulers'\n\n    @defer.inlineCallbacks\n    def get(self, resultSpec, kwargs):\n        l = []\n        builderid = kwargs.get('builderid', None)\n        if builderid is not None:\n            bdict = yield self.master.db.builders.getBuilder(builderid)\n        for sched in self.master.allSchedulers():\n            if isinstance(sched, forcesched.ForceScheduler):\n                if builderid is not None and bdict['name'] not in sched.builderNames:\n                    continue\n                l.append(forceScheduler2Data(sched))\n        defer.returnValue(l)\n\n\nclass ForceScheduler(base.ResourceType):\n\n    name = \"forcescheduler\"\n    plural = \"forceschedulers\"\n    endpoints = [ForceSchedulerEndpoint, ForceSchedulersEndpoint]\n    keyFields = []\n\n    class EntityType(types.Entity):\n        name = types.Identifier(20)\n        button_name = types.String()\n        label = types.String()\n        builder_names = types.List(of=types.Identifier(20))\n        all_fields = types.List(of=types.JsonObject())\n    entityType = EntityType(name)\n", "path": "master/buildbot/data/forceschedulers.py"}, {"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\nfrom twisted.internet import defer\n\nfrom buildbot.data import base\nfrom buildbot.data import types\n\n\nclass BuilderEndpoint(base.Endpoint):\n\n    isCollection = False\n    pathPatterns = \"\"\"\n        /builders/n:builderid\n        /masters/n:masterid/builders/n:builderid\n    \"\"\"\n\n    @defer.inlineCallbacks\n    def get(self, resultSpec, kwargs):\n        builderid = kwargs['builderid']\n        bdict = yield self.master.db.builders.getBuilder(builderid)\n        if not bdict:\n            defer.returnValue(None)\n            return\n        if 'masterid' in kwargs:\n            if kwargs['masterid'] not in bdict['masterids']:\n                defer.returnValue(None)\n                return\n        defer.returnValue(\n            dict(builderid=builderid,\n                 name=bdict['name'],\n                 masterids=bdict['masterids'],\n                 description=bdict['description'],\n                 tags=bdict['tags']))\n\n\nclass BuildersEndpoint(base.Endpoint):\n\n    isCollection = True\n    rootLinkName = 'builders'\n    pathPatterns = \"\"\"\n        /builders\n        /masters/n:masterid/builders\n    \"\"\"\n\n    @defer.inlineCallbacks\n    def get(self, resultSpec, kwargs):\n        bdicts = yield self.master.db.builders.getBuilders(\n            masterid=kwargs.get('masterid', None))\n        defer.returnValue([\n            dict(builderid=bd['id'],\n                 name=bd['name'],\n                 masterids=bd['masterids'],\n                 description=bd['description'],\n                 tags=bd['tags'])\n            for bd in bdicts])\n\n\nclass Builder(base.ResourceType):\n\n    name = \"builder\"\n    plural = \"builders\"\n    endpoints = [BuilderEndpoint, BuildersEndpoint]\n    keyFields = ['builderid']\n\n    class EntityType(types.Entity):\n        builderid = types.Integer()\n        name = types.Identifier(20)\n        masterids = types.List(of=types.Integer())\n        description = types.NoneOk(types.String())\n        tags = types.List(of=types.String())\n    entityType = EntityType(name)\n\n    def __init__(self, master):\n        base.ResourceType.__init__(self, master)\n\n    @base.updateMethod\n    def findBuilderId(self, name):\n        return self.master.db.builders.findBuilderId(name)\n\n    @base.updateMethod\n    def updateBuilderInfo(self, builderid, description, tags):\n        return self.master.db.builders.updateBuilderInfo(builderid, description, tags)\n\n    @base.updateMethod\n    @defer.inlineCallbacks\n    def updateBuilderList(self, masterid, builderNames):\n        # get the \"current\" list of builders for this master, so we know what\n        # changes to make.  Race conditions here aren't a great worry, as this\n        # is the only master inserting or deleting these records.\n        builders = yield self.master.db.builders.getBuilders(masterid=masterid)\n\n        # figure out what to remove and remove it\n        builderNames_set = set(builderNames)\n        for bldr in builders:\n            if bldr['name'] not in builderNames_set:\n                builderid = bldr['id']\n                yield self.master.db.builders.removeBuilderMaster(\n                    masterid=masterid, builderid=builderid)\n                self.master.mq.produce(('builders', str(builderid), 'stopped'),\n                                       dict(builderid=builderid, masterid=masterid,\n                                            name=bldr['name']))\n            else:\n                builderNames_set.remove(bldr['name'])\n\n        # now whatever's left in builderNames_set is new\n        for name in builderNames_set:\n            builderid = yield self.master.db.builders.findBuilderId(name)\n            yield self.master.db.builders.addBuilderMaster(\n                masterid=masterid, builderid=builderid)\n            self.master.mq.produce(('builders', str(builderid), 'started'),\n                                   dict(builderid=builderid, masterid=masterid, name=name))\n\n    @defer.inlineCallbacks\n    def _masterDeactivated(self, masterid):\n        # called from the masters rtype to indicate that the given master is\n        # deactivated\n        yield self.updateBuilderList(masterid, [])\n", "path": "master/buildbot/data/builders.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\nfrom twisted.internet import defer\n\nfrom buildbot.data import base\nfrom buildbot.data import types\nfrom buildbot.schedulers import forcesched\nfrom buildbot.www.rest import JSONRPC_CODES\nfrom buildbot.www.rest import BadJsonRpc2\n\n\ndef forceScheduler2Data(sched):\n    ret = dict(all_fields=[],\n               name=unicode(sched.name),\n               button_name=unicode(sched.buttonName),\n               label=unicode(sched.label),\n               builder_names=map(unicode, sched.builderNames))\n    ret[\"all_fields\"] = [field.getSpec() for field in sched.all_fields]\n    return ret\n\n\nclass ForceSchedulerEndpoint(base.Endpoint):\n\n    isCollection = False\n    pathPatterns = \"\"\"\n        /forceschedulers/i:schedulername\n    \"\"\"\n\n    def findForceScheduler(self, schedulername):\n        # eventually this may be db backed. This is why the API is async\n        for sched in self.master.allSchedulers():\n            if sched.name == schedulername and isinstance(sched, forcesched.ForceScheduler):\n                return defer.succeed(sched)\n\n    @defer.inlineCallbacks\n    def get(self, resultSpec, kwargs):\n        sched = yield self.findForceScheduler(kwargs['schedulername'])\n        if sched is not None:\n            defer.returnValue(forceScheduler2Data(sched))\n\n    @defer.inlineCallbacks\n    def control(self, action, args, kwargs):\n        if action == \"force\":\n            sched = yield self.findForceScheduler(kwargs['schedulername'])\n            if \"owner\" not in args:\n                args['owner'] = \"user\"\n            try:\n                res = yield sched.force(**args)\n                defer.returnValue(res)\n            except forcesched.CollectedValidationError as e:\n                raise BadJsonRpc2(e.errors, JSONRPC_CODES[\"invalid_params\"])\n        defer.returnValue(None)\n\n\nclass ForceSchedulersEndpoint(base.Endpoint):\n\n    isCollection = True\n    pathPatterns = \"\"\"\n        /forceschedulers\n        /builders/:builderid/forceschedulers\n    \"\"\"\n    rootLinkName = 'forceschedulers'\n\n    @defer.inlineCallbacks\n    def get(self, resultSpec, kwargs):\n        l = []\n        builderid = kwargs.get('builderid', None)\n        if builderid is not None:\n            bdict = yield self.master.db.builders.getBuilder(builderid)\n        for sched in self.master.allSchedulers():\n            if isinstance(sched, forcesched.ForceScheduler):\n                if builderid is not None and bdict['name'] not in sched.builderNames:\n                    continue\n                l.append(forceScheduler2Data(sched))\n        defer.returnValue(l)\n\n\nclass ForceScheduler(base.ResourceType):\n\n    name = \"forcescheduler\"\n    plural = \"forceschedulers\"\n    endpoints = [ForceSchedulerEndpoint, ForceSchedulersEndpoint]\n    keyFields = []\n\n    class EntityType(types.Entity):\n        name = types.Identifier(50)\n        button_name = types.String()\n        label = types.String()\n        builder_names = types.List(of=types.Identifier(50))\n        all_fields = types.List(of=types.JsonObject())\n    entityType = EntityType(name)\n", "path": "master/buildbot/data/forceschedulers.py"}, {"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\nfrom twisted.internet import defer\n\nfrom buildbot.data import base\nfrom buildbot.data import types\n\n\nclass BuilderEndpoint(base.Endpoint):\n\n    isCollection = False\n    pathPatterns = \"\"\"\n        /builders/n:builderid\n        /masters/n:masterid/builders/n:builderid\n    \"\"\"\n\n    @defer.inlineCallbacks\n    def get(self, resultSpec, kwargs):\n        builderid = kwargs['builderid']\n        bdict = yield self.master.db.builders.getBuilder(builderid)\n        if not bdict:\n            defer.returnValue(None)\n            return\n        if 'masterid' in kwargs:\n            if kwargs['masterid'] not in bdict['masterids']:\n                defer.returnValue(None)\n                return\n        defer.returnValue(\n            dict(builderid=builderid,\n                 name=bdict['name'],\n                 masterids=bdict['masterids'],\n                 description=bdict['description'],\n                 tags=bdict['tags']))\n\n\nclass BuildersEndpoint(base.Endpoint):\n\n    isCollection = True\n    rootLinkName = 'builders'\n    pathPatterns = \"\"\"\n        /builders\n        /masters/n:masterid/builders\n    \"\"\"\n\n    @defer.inlineCallbacks\n    def get(self, resultSpec, kwargs):\n        bdicts = yield self.master.db.builders.getBuilders(\n            masterid=kwargs.get('masterid', None))\n        defer.returnValue([\n            dict(builderid=bd['id'],\n                 name=bd['name'],\n                 masterids=bd['masterids'],\n                 description=bd['description'],\n                 tags=bd['tags'])\n            for bd in bdicts])\n\n\nclass Builder(base.ResourceType):\n\n    name = \"builder\"\n    plural = \"builders\"\n    endpoints = [BuilderEndpoint, BuildersEndpoint]\n    keyFields = ['builderid']\n\n    class EntityType(types.Entity):\n        builderid = types.Integer()\n        name = types.Identifier(50)\n        masterids = types.List(of=types.Integer())\n        description = types.NoneOk(types.String())\n        tags = types.List(of=types.String())\n    entityType = EntityType(name)\n\n    def __init__(self, master):\n        base.ResourceType.__init__(self, master)\n\n    @base.updateMethod\n    def findBuilderId(self, name):\n        return self.master.db.builders.findBuilderId(name)\n\n    @base.updateMethod\n    def updateBuilderInfo(self, builderid, description, tags):\n        return self.master.db.builders.updateBuilderInfo(builderid, description, tags)\n\n    @base.updateMethod\n    @defer.inlineCallbacks\n    def updateBuilderList(self, masterid, builderNames):\n        # get the \"current\" list of builders for this master, so we know what\n        # changes to make.  Race conditions here aren't a great worry, as this\n        # is the only master inserting or deleting these records.\n        builders = yield self.master.db.builders.getBuilders(masterid=masterid)\n\n        # figure out what to remove and remove it\n        builderNames_set = set(builderNames)\n        for bldr in builders:\n            if bldr['name'] not in builderNames_set:\n                builderid = bldr['id']\n                yield self.master.db.builders.removeBuilderMaster(\n                    masterid=masterid, builderid=builderid)\n                self.master.mq.produce(('builders', str(builderid), 'stopped'),\n                                       dict(builderid=builderid, masterid=masterid,\n                                            name=bldr['name']))\n            else:\n                builderNames_set.remove(bldr['name'])\n\n        # now whatever's left in builderNames_set is new\n        for name in builderNames_set:\n            builderid = yield self.master.db.builders.findBuilderId(name)\n            yield self.master.db.builders.addBuilderMaster(\n                masterid=masterid, builderid=builderid)\n            self.master.mq.produce(('builders', str(builderid), 'started'),\n                                   dict(builderid=builderid, masterid=masterid, name=name))\n\n    @defer.inlineCallbacks\n    def _masterDeactivated(self, masterid):\n        # called from the masters rtype to indicate that the given master is\n        # deactivated\n        yield self.updateBuilderList(masterid, [])\n", "path": "master/buildbot/data/builders.py"}]}