1 # Patchwork - automated patch tracking system
2 # Copyright (C) 2008 Nate Case <ncase@xes-inc.com>
4 # This file is part of the Patchwork package.
6 # Patchwork is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # Patchwork is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with Patchwork; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 # The XML-RPC interface provides a watered down, read-only interface to
21 # the Patchwork database. It's intended to be safe to export to the public
22 # Internet. A small subset of the object data is included, and the type
23 # of requests/queries you can do is limited by the methods
26 from patchwork.models import Patch, Project, Person, Bundle, State
28 # We allow most of the Django field lookup types for remote queries
29 LOOKUP_TYPES = ["iexact", "contains", "icontains", "gt", "gte", "lt",
30 "in", "startswith", "istartswith", "endswith",
31 "iendswith", "range", "year", "month", "day", "isnull" ]
33 #######################################################################
35 #######################################################################
37 def project_to_dict(obj):
38 """Return a trimmed down dictionary representation of a Project
39 object which is OK to send to the client."""
43 'linkname' : obj.linkname,
47 def person_to_dict(obj):
48 """Return a trimmed down dictionary representation of a Person
49 object which is OK to send to the client."""
55 'user' : str(obj.user),
58 def patch_to_dict(obj):
59 """Return a trimmed down dictionary representation of a Patch
60 object which is OK to send to the client."""
64 'date' : str(obj.date),
65 'filename' : obj.filename(),
68 'project' : str(obj.project),
69 'project_id' : obj.project_id,
70 'state' : str(obj.state),
71 'state_id' : obj.state_id,
72 'submitter' : str(obj.submitter),
73 'submitter_id' : obj.submitter_id,
74 'delegate' : str(obj.delegate),
75 'delegate_id' : max(obj.delegate_id, 0),
76 'commit_ref' : max(obj.commit_ref, ''),
79 def bundle_to_dict(obj):
80 """Return a trimmed down dictionary representation of a Bundle
81 object which is OK to send to the client."""
86 'n_patches' : obj.n_patches(),
87 'public_url' : obj.public_url(),
90 def state_to_dict(obj):
91 """Return a trimmed down dictionary representation of a State
92 object which is OK to send to the client."""
99 #######################################################################
100 # Public XML-RPC methods
101 #######################################################################
103 def pw_rpc_version():
104 """Return Patchwork XML-RPC interface version."""
107 def project_list(search_str="", max_count=0):
108 """Get a list of projects matching the given filters."""
110 if len(search_str) > 0:
111 projects = Project.objects.filter(name__icontains = search_str)
113 projects = Project.objects.all()
116 return map(project_to_dict, projects)[:max_count]
118 return map(project_to_dict, projects)
122 def project_get(project_id):
123 """Return structure for the given project ID."""
125 project = Project.objects.filter(id = project_id)[0]
126 return project_to_dict(project)
130 def person_list(search_str="", max_count=0):
131 """Get a list of Person objects matching the given filters."""
133 if len(search_str) > 0:
134 people = (Person.objects.filter(name__icontains = search_str) |
135 Person.objects.filter(email__icontains = search_str))
137 people = Person.objects.all()
140 return map(person_to_dict, people)[:max_count]
142 return map(person_to_dict, people)
147 def person_get(person_id):
148 """Return structure for the given person ID."""
150 person = Person.objects.filter(id = person_id)[0]
151 return person_to_dict(person)
155 def patch_list(filter={}):
156 """Get a list of patches matching the given filters."""
158 # We allow access to many of the fields. But, some fields are
159 # filtered by raw object so we must lookup by ID instead over
180 parts = key.split("__")
181 if ok_fields.count(parts[0]) == 0:
182 # Invalid field given
185 if LOOKUP_TYPES.count(parts[1]) == 0:
186 # Invalid lookup type given
189 if parts[0] == 'project_id':
190 dfilter['project'] = Project.objects.filter(id =
192 elif parts[0] == 'submitter_id':
193 dfilter['submitter'] = Person.objects.filter(id =
195 elif parts[0] == 'state_id':
196 dfilter['state'] = State.objects.filter(id =
198 elif parts[0] == 'max_count':
199 max_count = filter[key]
201 dfilter[key] = filter[key]
203 patches = Patch.objects.filter(**dfilter)
206 return map(patch_to_dict, patches)[:max_count]
208 return map(patch_to_dict, patches)
213 def patch_get(patch_id):
214 """Return structure for the given patch ID."""
216 patch = Patch.objects.filter(id = patch_id)[0]
217 return patch_to_dict(patch)
221 def patch_get_mbox(patch_id):
222 """Return mbox string for the given patch ID."""
224 patch = Patch.objects.filter(id = patch_id)[0]
225 return patch.mbox().as_string()
229 def patch_get_diff(patch_id):
230 """Return diff for the given patch ID."""
232 patch = Patch.objects.filter(id = patch_id)[0]
237 def state_list(search_str="", max_count=0):
238 """Get a list of state structures matching the given search string."""
240 if len(search_str) > 0:
241 states = State.objects.filter(name__icontains = search_str)
243 states = State.objects.all()
246 return map(state_to_dict, states)[:max_count]
248 return map(state_to_dict, states)
252 def state_get(state_id):
253 """Return structure for the given state ID."""
255 state = State.objects.filter(id = state_id)[0]
256 return state_to_dict(state)