comparison env/lib/python3.7/site-packages/rdflib/extras/describer.py @ 5:9b1c78e6ba9c draft default tip

"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author shellac
date Mon, 01 Jun 2020 08:59:25 -0400
parents 79f47841a781
children
comparison
equal deleted inserted replaced
4:79f47841a781 5:9b1c78e6ba9c
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 from rdflib import py3compat
5 __doc__ = py3compat.format_doctest_out("""
6 A Describer is a stateful utility for creating RDF statements in a
7 semi-declarative manner. It has methods for creating literal values, rel and
8 rev resource relations (somewhat resembling RDFa).
9
10 The `rel` and ``rev`` methods return a context manager which sets the current
11 about to the referenced resource for the context scope (for use with the
12 ``with`` statement).
13
14 Full example in the ``to_rdf`` method below::
15
16 >>> import datetime
17 >>> from rdflib.graph import Graph
18 >>> from rdflib.namespace import Namespace, RDFS, FOAF
19 >>>
20 >>> ORG_URI = "http://example.org/"
21 >>>
22 >>> CV = Namespace("http://purl.org/captsolo/resume-rdf/0.2/cv#")
23 >>>
24 >>> class Person(object):
25 ... def __init__(self):
26 ... self.first_name = %(u)s"Some"
27 ... self.last_name = %(u)s"Body"
28 ... self.username = "some1"
29 ... self.presentation = %(u)s"Just a Python & RDF hacker."
30 ... self.image = "/images/persons/" + self.username + ".jpg"
31 ... self.site = "http://example.net/"
32 ... self.start_date = datetime.date(2009, 9, 4)
33 ... def get_full_name(self):
34 ... return %(u)s" ".join([self.first_name, self.last_name])
35 ... def get_absolute_url(self):
36 ... return "/persons/" + self.username
37 ... def get_thumbnail_url(self):
38 ... return self.image.replace('.jpg', '-thumb.jpg')
39 ...
40 ... def to_rdf(self):
41 ... graph = Graph()
42 ... graph.bind('foaf', FOAF)
43 ... graph.bind('cv', CV)
44 ... lang = 'en'
45 ... d = Describer(graph, base=ORG_URI)
46 ... d.about(self.get_absolute_url()+'#person')
47 ... d.rdftype(FOAF.Person)
48 ... d.value(FOAF.name, self.get_full_name())
49 ... d.value(FOAF.firstName, self.first_name)
50 ... d.value(FOAF.surname, self.last_name)
51 ... d.rel(FOAF.homepage, self.site)
52 ... d.value(RDFS.comment, self.presentation, lang=lang)
53 ... with d.rel(FOAF.depiction, self.image):
54 ... d.rdftype(FOAF.Image)
55 ... d.rel(FOAF.thumbnail, self.get_thumbnail_url())
56 ... with d.rev(CV.aboutPerson):
57 ... d.rdftype(CV.CV)
58 ... with d.rel(CV.hasWorkHistory):
59 ... d.value(CV.startDate, self.start_date)
60 ... d.rel(CV.employedIn, ORG_URI+"#company")
61 ... return graph
62 ...
63 >>> person_graph = Person().to_rdf()
64 >>> expected = Graph().parse(data='''<?xml version="1.0" encoding="utf-8"?>
65 ... <rdf:RDF
66 ... xmlns:foaf="http://xmlns.com/foaf/0.1/"
67 ... xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
68 ... xmlns:cv="http://purl.org/captsolo/resume-rdf/0.2/cv#"
69 ... xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
70 ... <foaf:Person rdf:about="http://example.org/persons/some1#person">
71 ... <foaf:name>Some Body</foaf:name>
72 ... <foaf:firstName>Some</foaf:firstName>
73 ... <foaf:surname>Body</foaf:surname>
74 ... <foaf:depiction>
75 ... <foaf:Image
76 ... rdf:about=
77 ... "http://example.org/images/persons/some1.jpg">
78 ... <foaf:thumbnail
79 ... rdf:resource=
80 ... "http://example.org/images/persons/some1-thumb.jpg"/>
81 ... </foaf:Image>
82 ... </foaf:depiction>
83 ... <rdfs:comment xml:lang="en">
84 ... Just a Python &amp; RDF hacker.
85 ... </rdfs:comment>
86 ... <foaf:homepage rdf:resource="http://example.net/"/>
87 ... </foaf:Person>
88 ... <cv:CV>
89 ... <cv:aboutPerson
90 ... rdf:resource="http://example.org/persons/some1#person">
91 ... </cv:aboutPerson>
92 ... <cv:hasWorkHistory>
93 ... <rdf:Description>
94 ... <cv:startDate
95 ... rdf:datatype="http://www.w3.org/2001/XMLSchema#date"
96 ... >2009-09-04</cv:startDate>
97 ... <cv:employedIn rdf:resource="http://example.org/#company"/>
98 ... </rdf:Description>
99 ... </cv:hasWorkHistory>
100 ... </cv:CV>
101 ... </rdf:RDF>
102 ... ''')
103 >>>
104 >>> from rdflib.compare import isomorphic
105 >>> isomorphic(person_graph, expected) #doctest: +SKIP
106 True
107 """)
108
109 from contextlib import contextmanager
110 from rdflib.graph import Graph
111 from rdflib.namespace import RDF
112 from rdflib.term import BNode
113 from rdflib.term import Identifier
114 from rdflib.term import Literal
115 from rdflib.term import URIRef
116 from rdflib.py3compat import format_doctest_out
117
118
119 class Describer(object):
120
121 def __init__(self, graph=None, about=None, base=None):
122 if graph is None:
123 graph = Graph()
124 self.graph = graph
125 self.base = base
126 self._subjects = []
127 self.about(about or None)
128
129 @format_doctest_out
130 def about(self, subject, **kws):
131 """
132 Sets the current subject. Will convert the given object into an
133 ``URIRef`` if it's not an ``Identifier``.
134
135 Usage::
136
137 >>> d = Describer()
138 >>> d._current() #doctest: +ELLIPSIS
139 rdflib.term.BNode(...)
140 >>> d.about("http://example.org/")
141 >>> d._current()
142 rdflib.term.URIRef(%(u)s'http://example.org/')
143
144 """
145 kws.setdefault('base', self.base)
146 subject = cast_identifier(subject, **kws)
147 if self._subjects:
148 self._subjects[-1] = subject
149 else:
150 self._subjects.append(subject)
151
152 @format_doctest_out
153 def value(self, p, v, **kws):
154 """
155 Set a literal value for the given property. Will cast the value to an
156 ``Literal`` if a plain literal is given.
157
158 Usage::
159
160 >>> from rdflib import URIRef
161 >>> from rdflib.namespace import RDF, RDFS
162 >>> d = Describer(about="http://example.org/")
163 >>> d.value(RDFS.label, "Example")
164 >>> d.graph.value(URIRef('http://example.org/'), RDFS.label)
165 rdflib.term.Literal(%(u)s'Example')
166
167 """
168 v = cast_value(v, **kws)
169 self.graph.add((self._current(), p, v))
170
171 @format_doctest_out
172 def rel(self, p, o=None, **kws):
173 """Set an object for the given property. Will convert the given object
174 into an ``URIRef`` if it's not an ``Identifier``. If none is given, a
175 new ``BNode`` is used.
176
177 Returns a context manager for use in a ``with`` block, within which the
178 given object is used as current subject.
179
180 Usage::
181
182 >>> from rdflib import URIRef
183 >>> from rdflib.namespace import RDF, RDFS
184 >>> d = Describer(about="/", base="http://example.org/")
185 >>> _ctxt = d.rel(RDFS.seeAlso, "/about")
186 >>> d.graph.value(URIRef('http://example.org/'), RDFS.seeAlso)
187 rdflib.term.URIRef(%(u)s'http://example.org/about')
188
189 >>> with d.rel(RDFS.seeAlso, "/more"):
190 ... d.value(RDFS.label, "More")
191 >>> (URIRef('http://example.org/'), RDFS.seeAlso,
192 ... URIRef('http://example.org/more')) in d.graph
193 True
194 >>> d.graph.value(URIRef('http://example.org/more'), RDFS.label)
195 rdflib.term.Literal(%(u)s'More')
196
197 """
198
199 kws.setdefault('base', self.base)
200 p = cast_identifier(p)
201 o = cast_identifier(o, **kws)
202 self.graph.add((self._current(), p, o))
203 return self._subject_stack(o)
204
205 @format_doctest_out
206 def rev(self, p, s=None, **kws):
207 """
208 Same as ``rel``, but uses current subject as *object* of the relation.
209 The given resource is still used as subject in the returned context
210 manager.
211
212 Usage::
213
214 >>> from rdflib import URIRef
215 >>> from rdflib.namespace import RDF, RDFS
216 >>> d = Describer(about="http://example.org/")
217 >>> with d.rev(RDFS.seeAlso, "http://example.net/"):
218 ... d.value(RDFS.label, "Net")
219 >>> (URIRef('http://example.net/'), RDFS.seeAlso,
220 ... URIRef('http://example.org/')) in d.graph
221 True
222 >>> d.graph.value(URIRef('http://example.net/'), RDFS.label)
223 rdflib.term.Literal(%(u)s'Net')
224
225 """
226 kws.setdefault('base', self.base)
227 p = cast_identifier(p)
228 s = cast_identifier(s, **kws)
229 self.graph.add((s, p, self._current()))
230 return self._subject_stack(s)
231
232 def rdftype(self, t):
233 """
234 Shorthand for setting rdf:type of the current subject.
235
236 Usage::
237
238 >>> from rdflib import URIRef
239 >>> from rdflib.namespace import RDF, RDFS
240 >>> d = Describer(about="http://example.org/")
241 >>> d.rdftype(RDFS.Resource)
242 >>> (URIRef('http://example.org/'),
243 ... RDF.type, RDFS.Resource) in d.graph
244 True
245
246 """
247 self.graph.add((self._current(), RDF.type, t))
248
249 def _current(self):
250 return self._subjects[-1]
251
252 @contextmanager
253 def _subject_stack(self, subject):
254 self._subjects.append(subject)
255 yield None
256 self._subjects.pop()
257
258
259 def cast_value(v, **kws):
260 if not isinstance(v, Literal):
261 v = Literal(v, **kws)
262 return v
263
264
265 def cast_identifier(ref, **kws):
266 ref = ref or BNode()
267 if not isinstance(ref, Identifier):
268 ref = URIRef(ref, **kws)
269 return ref