comparison env/lib/python3.9/site-packages/rdflib/collection.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 from __future__ import absolute_import
2 from __future__ import division
3 from __future__ import print_function
4
5 from rdflib.namespace import RDF
6 from rdflib.term import BNode
7 from rdflib.term import Literal
8
9
10 __all__ = ['Collection']
11
12
13 class Collection(object):
14 __doc__ = """
15 See "Emulating container types":
16 https://docs.python.org/reference/datamodel.html#emulating-container-types
17
18 >>> from rdflib.graph import Graph
19 >>> from pprint import pprint
20 >>> listName = BNode()
21 >>> g = Graph('IOMemory')
22 >>> listItem1 = BNode()
23 >>> listItem2 = BNode()
24 >>> g.add((listName, RDF.first, Literal(1)))
25 >>> g.add((listName, RDF.rest, listItem1))
26 >>> g.add((listItem1, RDF.first, Literal(2)))
27 >>> g.add((listItem1, RDF.rest, listItem2))
28 >>> g.add((listItem2, RDF.rest, RDF.nil))
29 >>> g.add((listItem2, RDF.first, Literal(3)))
30 >>> c = Collection(g,listName)
31 >>> pprint([term.n3() for term in c])
32 [u'"1"^^<http://www.w3.org/2001/XMLSchema#integer>',
33 u'"2"^^<http://www.w3.org/2001/XMLSchema#integer>',
34 u'"3"^^<http://www.w3.org/2001/XMLSchema#integer>']
35
36 >>> Literal(1) in c
37 True
38 >>> len(c)
39 3
40 >>> c._get_container(1) == listItem1
41 True
42 >>> c.index(Literal(2)) == 1
43 True
44 """
45
46 def __init__(self, graph, uri, seq=[]):
47 self.graph = graph
48 self.uri = uri or BNode()
49 self += seq
50
51 def n3(self):
52 """
53 >>> from rdflib.graph import Graph
54 >>> listName = BNode()
55 >>> g = Graph('IOMemory')
56 >>> listItem1 = BNode()
57 >>> listItem2 = BNode()
58 >>> g.add((listName, RDF.first, Literal(1)))
59 >>> g.add((listName, RDF.rest, listItem1))
60 >>> g.add((listItem1, RDF.first, Literal(2)))
61 >>> g.add((listItem1, RDF.rest, listItem2))
62 >>> g.add((listItem2, RDF.rest, RDF.nil))
63 >>> g.add((listItem2, RDF.first, Literal(3)))
64 >>> c = Collection(g, listName)
65 >>> print(c.n3()) #doctest: +NORMALIZE_WHITESPACE
66 ( "1"^^<http://www.w3.org/2001/XMLSchema#integer>
67 "2"^^<http://www.w3.org/2001/XMLSchema#integer>
68 "3"^^<http://www.w3.org/2001/XMLSchema#integer> )
69 """
70 return "( %s )" % (' '.join([i.n3() for i in self]))
71
72 def _get_container(self, index):
73 """Gets the first, rest holding node at index."""
74 assert isinstance(index, int)
75 graph = self.graph
76 container = self.uri
77 i = 0
78 while i < index:
79 i += 1
80 container = graph.value(container, RDF.rest)
81 if container is None:
82 break
83 return container
84
85 def __len__(self):
86 """length of items in collection."""
87 return len(list(self.graph.items(self.uri)))
88
89 def index(self, item):
90 """
91 Returns the 0-based numerical index of the item in the list
92 """
93 listName = self.uri
94 index = 0
95 while True:
96 if (listName, RDF.first, item) in self.graph:
97 return index
98 else:
99 newLink = list(self.graph.objects(listName, RDF.rest))
100 index += 1
101 if newLink == [RDF.nil]:
102 raise ValueError("%s is not in %s" % (item, self.uri))
103 elif not newLink:
104 raise Exception("Malformed RDF Collection: %s" % self.uri)
105 else:
106 assert len(newLink) == 1, \
107 "Malformed RDF Collection: %s" % self.uri
108 listName = newLink[0]
109
110 def __getitem__(self, key):
111 """TODO"""
112 c = self._get_container(key)
113 if c:
114 v = self.graph.value(c, RDF.first)
115 if v:
116 return v
117 else:
118 raise KeyError(key)
119 else:
120 raise IndexError(key)
121
122 def __setitem__(self, key, value):
123 """TODO"""
124 c = self._get_container(key)
125 if c:
126 self.graph.set((c, RDF.first, value))
127 else:
128 raise IndexError(key)
129
130 def __delitem__(self, key):
131 """
132 >>> from rdflib.namespace import RDF, RDFS
133 >>> from rdflib import Graph
134 >>> from pprint import pformat
135 >>> g = Graph()
136 >>> a = BNode('foo')
137 >>> b = BNode('bar')
138 >>> c = BNode('baz')
139 >>> g.add((a, RDF.first, RDF.type))
140 >>> g.add((a, RDF.rest, b))
141 >>> g.add((b, RDF.first, RDFS.label))
142 >>> g.add((b, RDF.rest, c))
143 >>> g.add((c, RDF.first, RDFS.comment))
144 >>> g.add((c, RDF.rest, RDF.nil))
145 >>> len(g)
146 6
147 >>> def listAncestry(node, graph):
148 ... for i in graph.subjects(RDF.rest, node):
149 ... yield i
150 >>> [str(node.n3())
151 ... for node in g.transitiveClosure(listAncestry, RDF.nil)]
152 ['_:baz', '_:bar', '_:foo']
153 >>> lst = Collection(g, a)
154 >>> len(lst)
155 3
156 >>> b == lst._get_container(1)
157 True
158 >>> c == lst._get_container(2)
159 True
160 >>> del lst[1]
161 >>> len(lst)
162 2
163 >>> len(g)
164 4
165
166 """
167 self[key] # to raise any potential key exceptions
168 graph = self.graph
169 current = self._get_container(key)
170 assert current
171 if len(self) == 1 and key > 0:
172 pass
173 elif key == len(self) - 1:
174 # the tail
175 priorLink = self._get_container(key - 1)
176 self.graph.set((priorLink, RDF.rest, RDF.nil))
177 graph.remove((current, None, None))
178 else:
179 next = self._get_container(key + 1)
180 prior = self._get_container(key - 1)
181 assert next and prior
182 graph.remove((current, None, None))
183 graph.set((prior, RDF.rest, next))
184
185 def __iter__(self):
186 """Iterator over items in Collections"""
187 return self.graph.items(self.uri)
188
189 def _end(self):
190 # find end of list
191 container = self.uri
192 while True:
193 rest = self.graph.value(container, RDF.rest)
194 if rest is None or rest == RDF.nil:
195 return container
196 else:
197 container = rest
198
199 def append(self, item):
200 """
201 >>> from rdflib.graph import Graph
202 >>> listName = BNode()
203 >>> g = Graph()
204 >>> c = Collection(g,listName,[Literal(1),Literal(2)])
205 >>> links = [
206 ... list(g.subjects(object=i, predicate=RDF.first))[0] for i in c]
207 >>> len([i for i in links if (i, RDF.rest, RDF.nil) in g])
208 1
209
210 """
211
212 end = self._end()
213 if (end, RDF.first, None) in self.graph:
214 # append new node to the end of the linked list
215 node = BNode()
216 self.graph.set((end, RDF.rest, node))
217 end = node
218
219 self.graph.add((end, RDF.first, item))
220 self.graph.add((end, RDF.rest, RDF.nil))
221
222 def __iadd__(self, other):
223
224 end = self._end()
225 self.graph.remove((end, RDF.rest, None))
226
227 for item in other:
228 if (end, RDF.first, None) in self.graph:
229 nxt = BNode()
230 self.graph.add((end, RDF.rest, nxt))
231 end = nxt
232
233 self.graph.add((end, RDF.first, item))
234
235 self.graph.add((end, RDF.rest, RDF.nil))
236
237 def clear(self):
238 container = self.uri
239 graph = self.graph
240 while container:
241 rest = graph.value(container, RDF.rest)
242 graph.remove((container, RDF.first, None))
243 graph.remove((container, RDF.rest, None))
244 container = rest
245
246
247 def test():
248 import doctest
249 doctest.testmod()
250
251
252 if __name__ == "__main__":
253 test()
254
255 from rdflib import Graph
256 g = Graph()
257
258 c = Collection(g, BNode())
259
260 assert len(c) == 0
261
262 c = Collection(
263 g, BNode(), [Literal("1"), Literal("2"), Literal("3"), Literal("4")])
264
265 assert len(c) == 4
266
267 assert c[1] == Literal("2"), c[1]
268
269 del c[1]
270
271 assert list(c) == [Literal("1"), Literal("3"), Literal("4")], list(c)
272
273 try:
274 del c[500]
275 except IndexError as i:
276 pass
277
278 c.append(Literal("5"))
279
280 print(list(c))
281
282 for i in c:
283 print(i)
284
285 del c[3]
286
287 c.clear()
288
289 assert len(c) == 0