1
2
3
4 """
5
6 Library for parsing, displaying, querying and serializing DOAP
7
8 """
9
10 import sys
11 import xmlrpclib
12 from cStringIO import StringIO
13 from xml.sax._exceptions import SAXParseException
14
15 from rdfalchemy import rdfSubject
16 from rdflib import ConjunctiveGraph, Namespace
17
18 from doapfiend.utils import fetch_file
19 from doapfiend.model import Project
20 from doapfiend.plugins import load_plugins
21
22 XMLRPC_SERVER = xmlrpclib.ServerProxy('http://doapspace.org/xmlrpc/')
23 DOAP_NS = Namespace('http://usefulinc.com/ns/doap#')
24
25
26 -def follow_homepages(rdf_xml):
27 '''
28 If there is a 'doap:Project homepage' it will be looked up
29 on doapspace.org using get_by_homepage to find any other
30 DOAP. This is useful if we're looking at FOAF and a project
31 is mentioned by homepage. It can also be used on DOAP files
32 to search for additional DOAP files about the same project.
33
34 @param rdf_xml: RDF serialized as XML
35 @type : string
36
37 @rtype: int
38 @returns: 0 on sucess or 1 if there was no DOAP in the RDF
39 '''
40 homepages = list(get_homepages(rdf_xml))
41 nbr_homepage_urls = len(homepages)
42 if nbr_homepage_urls >= 1:
43 print_doap_by_homepages(homepages)
44 else:
45 print 'No DOAP found in that RDF.'
46 return 1
47
48
50 '''
51 If there is a 'doap:Project homepage' it will be looked up
52 on doapspace.org using get_by_homepage to find any other
53 DOAP. This is useful if we're looking at FOAF and a project
54 is mentioned by homepage. It can also be used on DOAP files
55 to search for additional DOAP files about the same project.
56
57 @param rdf: RDF serialized as XML
58 @type : string
59
60 @rtype: int
61 @returns: 0 on sucess or 1 if there was no DOAP in the RDF
62 '''
63 homepages = list(get_homepages(rdf))
64 nbr_homepage_urls = len(homepages)
65 if nbr_homepage_urls >= 1:
66 for hpage_url in homepages:
67 print "Found project homepage:", hpage_url
68
69 hpages = query_by_homepage(hpage_url)
70 for _src, hpage_url in hpages:
71 print ' Found DOAP: ', hpage_url
72 else:
73 print 'No DOAP found in that RDF.'
74 return 1
75
76
78 '''
79 Given a list of homepage URLs, search for DOAP for each and print
80
81 @param homepages: Project homepage
82 @type : list
83
84 @rtype: None
85 @returns: None
86 '''
87 for hpage_url in homepages:
88 print "Found project homepage", hpage_url
89
90 hpages = query_by_homepage(hpage_url)
91 for _src, hpage_url in hpages:
92 print 'Found DOAP at ', hpage_url
93 doap_xml = fetch_doap(hpage_url)
94 print_doap(doap_xml)
95
96 -def get_homepages(rdf, format='xml'):
97 '''
98 Find all doap:homepage in RDF
99
100 @param rdf: RDF
101 @type rdf: string
102
103 @param format: Serialization format
104 @type format: string
105
106 @rtype: generator
107 @returns: homepages
108 '''
109 store = ConjunctiveGraph()
110 store.parse(StringIO(rdf), publicID=None, format=format)
111 if rdf_has_doap(store):
112 for _s, o in store.subject_objects(DOAP_NS["homepage"]):
113 yield(str(o))
114
116 '''
117 Returns True if triplestore has the DOAP namespace defined
118
119 @param store: triplestore
120 @type store: rdflib ConjunctiveGraph
121
122 @rtype: boolean
123 @returns: True if triplestore contains DOAP namespace
124
125 '''
126 for namespace in store.namespaces():
127 if namespace[1] == DOAP_NS:
128 return True
129
131 '''
132 Load a DOAP profile into a RDFAlchemy/rdflib graph
133
134 Supports any serialization format rdflib can parse (xml, n3, etc.)
135
136 @param doap: DOAP
137 @type doap: string
138
139 @param format: Serialization format we're parsing
140 @type format: string
141
142 @rtype: Project
143 @returns: a Project{rdfSubject}
144
145 '''
146 rdfSubject.db = ConjunctiveGraph()
147 try:
148 rdfSubject.db.parse(StringIO(doap), format)
149 except SAXParseException:
150 sys.stderr.write("Error: Can't parse RDF/XML.\n")
151 sys.exit(2)
152
153 if next:
154 try:
155 return Project.ClassInstances().next()
156 except StopIteration:
157 sys.stderr.write('No DOAP found in that RDF.\n')
158 sys.exit(2)
159 else:
160 return Project
161
162
164 '''
165 Get DOAP for a package index project name
166
167 Builtin indexes:
168
169 - 'sf' SourceForge
170 - 'fm' Freshmeat
171 - 'py' Python Package Index
172
173 Note there can be other package indexes available by
174 third party plugins.
175
176 @param index: Package index two letter abbreviation
177 @type index: string
178
179 @param project_name: project name
180 @type project_name: string
181
182 @param proxy: Optional HTTP proxy URL
183 @type proxy: string
184
185 @rtype: string
186 @return: text of file retrieved
187
188 '''
189 for plugin_obj in list(load_plugins()):
190 plugin = plugin_obj()
191 if hasattr(plugin, 'prefix'):
192 if plugin.prefix == index:
193 plugin.query = project_name
194 return plugin.search(proxy)
195
196
198 '''
199 Get list of URL's for DOAP given a project's homepage.
200 The list can contain zero or multiple URLs.
201
202 The return format is:
203 [(source, URL), (source, URL)...]
204
205 'source' is the two letter package index abbreviation or 'ex' for external.
206 'external' meaning the DOAP was spidered on the web.
207 Possible package indexes:
208
209 Current indexes:
210
211 - 'sf' SourceForge
212 - 'fm' Freshmeat
213 - 'py' Python Package Index
214 - 'oh' Packages listed on Ohloh
215
216 @param url: URL of homepage of a project
217 @type url: string
218
219 @rtype: list
220 @return: A list of tuples containing URLs for DOAP found by homepage
221
222 '''
223
224 return XMLRPC_SERVER.query_by_homepage(url)
225
226
227 -def print_doap(doap_xml, color=None, format='text', serializer=None,
228 filename=None):
229 '''
230 Print DOAP as text, xml, or n3 etc. or to stdout or a file
231 A callable serializer object may be passed or a name of a serializer
232 plugin.
233
234 @param doap_xml: DOAP profile in RDF/XML
235 @type doap_xml: string
236
237 @param format: Serialization syntax formatter name
238 @type format: string
239
240 @param serializer: Instance of a serializer
241 @type serializer: callable
242
243 @param filename: Optional filename to write to
244 @type filename: string
245
246 @return: `serializer` or 1 if invalid serialization request
247
248 '''
249
250
251 if not serializer:
252 serializer = get_serializer(format)
253 if not serializer:
254 sys.stderr.write('Unknown serialization requested: %s\n' % format)
255 return 1
256
257 doap = serializer(doap_xml, color)
258 if filename:
259 try:
260 open(filename, 'w').write(doap.encode('utf-8'))
261 except UnicodeDecodeError:
262 open(filename, 'w').write(doap)
263 else:
264 print doap
265
266
268 '''
269 Return a serializer instance given its name
270
271 @param format: Name of serializer
272 @type format: string
273
274 @rtype: function
275 @returns: Instance of a serializer
276 '''
277
278 for plugin_obj in get_plugin('serialize'):
279 plugin = plugin_obj()
280 if plugin.name == format:
281 return plugin.serialize
282
283
285 """
286 Return plugin object if `method` exists
287
288 @param method: name of plugin's method we're calling
289 @type method: string
290
291 @returns: list of plugins with `method`
292
293 """
294 all_plugins = []
295 for plugin in load_plugins():
296
297 if not hasattr(plugin, method):
298 plugin = None
299 else:
300 all_plugins.append(plugin)
301 return all_plugins
302
303
305 '''
306 Fetch DOAP by its URL or filename
307
308 @param url: URL of DOAP profile in RDF/XML serialization
309 @type url: string
310
311 @rtype: text
312 @return: DOAP
313 '''
314 return fetch_file(url, proxy)
315