comparison env/lib/python3.7/site-packages/rdflib/collection.py @ 0:26e78fe6e8c4 draft

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