pyjelly 0.2.3__py3-none-any.whl → 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyjelly might be problematic. Click here for more details.
- pyjelly/integrations/rdflib/parse.py +364 -166
- pyjelly/integrations/rdflib/serialize.py +168 -43
- pyjelly/jelly/rdf_pb2.py +3 -3
- pyjelly/jelly/rdf_pb2.pyi +2 -1
- pyjelly/parse/decode.py +166 -5
- pyjelly/parse/ioutils.py +26 -4
- pyjelly/serialize/encode.py +117 -0
- pyjelly/serialize/flows.py +70 -13
- pyjelly/serialize/streams.py +87 -3
- {pyjelly-0.2.3.dist-info → pyjelly-0.4.0.dist-info}/METADATA +8 -8
- {pyjelly-0.2.3.dist-info → pyjelly-0.4.0.dist-info}/RECORD +14 -14
- {pyjelly-0.2.3.dist-info → pyjelly-0.4.0.dist-info}/WHEEL +0 -0
- {pyjelly-0.2.3.dist-info → pyjelly-0.4.0.dist-info}/entry_points.txt +0 -0
- {pyjelly-0.2.3.dist-info → pyjelly-0.4.0.dist-info}/licenses/LICENSE +0 -0
pyjelly/serialize/encode.py
CHANGED
|
@@ -11,6 +11,16 @@ from pyjelly.serialize.lookup import LookupEncoder
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def split_iri(iri_string: str) -> tuple[str, str]:
|
|
14
|
+
"""
|
|
15
|
+
Split iri into prefix and name.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
iri_string (str): full iri string.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
tuple[str, str]: iri's prefix and name.
|
|
22
|
+
|
|
23
|
+
"""
|
|
14
24
|
name = iri_string
|
|
15
25
|
prefix = ""
|
|
16
26
|
for sep in "#", "/":
|
|
@@ -47,6 +57,16 @@ class TermEncoder:
|
|
|
47
57
|
self.datatypes = LookupEncoder(lookup_size=lookup_preset.max_datatypes)
|
|
48
58
|
|
|
49
59
|
def encode_iri(self, iri_string: str) -> RowsAnd[jelly.RdfIri]:
|
|
60
|
+
"""
|
|
61
|
+
Encode iri.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
iri_string (str): full iri in string format.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
RowsAnd[jelly.RdfIri]: extra rows and protobuf RdfIri message.
|
|
68
|
+
|
|
69
|
+
"""
|
|
50
70
|
prefix, name = split_iri(iri_string)
|
|
51
71
|
if self.prefixes.lookup.max_size:
|
|
52
72
|
prefix_entry_index = self.prefixes.encode_entry_index(prefix)
|
|
@@ -70,9 +90,27 @@ class TermEncoder:
|
|
|
70
90
|
return term_rows, jelly.RdfIri(prefix_id=prefix_index, name_id=name_index)
|
|
71
91
|
|
|
72
92
|
def encode_default_graph(self) -> RowsAnd[jelly.RdfDefaultGraph]:
|
|
93
|
+
"""
|
|
94
|
+
Encode default graph.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
RowsAnd[jelly.RdfDefaultGraph]: empty extra rows and
|
|
98
|
+
default graph message.
|
|
99
|
+
|
|
100
|
+
"""
|
|
73
101
|
return (), jelly.RdfDefaultGraph()
|
|
74
102
|
|
|
75
103
|
def encode_bnode(self, bnode: str) -> RowsAnd[str]:
|
|
104
|
+
"""
|
|
105
|
+
Encode blank node (BN).
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
bnode (str): BN internal identifier in string format.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
RowsAnd[str]: empty extra rows and original BN string.
|
|
112
|
+
|
|
113
|
+
"""
|
|
76
114
|
return (), bnode
|
|
77
115
|
|
|
78
116
|
def encode_literal(
|
|
@@ -82,6 +120,24 @@ class TermEncoder:
|
|
|
82
120
|
language: str | None = None,
|
|
83
121
|
datatype: str | None = None,
|
|
84
122
|
) -> RowsAnd[jelly.RdfLiteral]:
|
|
123
|
+
"""
|
|
124
|
+
Encode literal.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
lex (str): lexical form/literal value
|
|
128
|
+
language (str | None, optional): langtag. Defaults to None.
|
|
129
|
+
datatype (str | None, optional): data type if
|
|
130
|
+
it is a typed literal. Defaults to None.
|
|
131
|
+
|
|
132
|
+
Raises:
|
|
133
|
+
JellyConformanceError: if datatype specified while
|
|
134
|
+
datatable is not used.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
RowsAnd[jelly.RdfLiteral]: extra rows (i.e., datatype entries)
|
|
138
|
+
and RdfLiteral message.
|
|
139
|
+
|
|
140
|
+
"""
|
|
85
141
|
datatype_id = None
|
|
86
142
|
term_rows: tuple[()] | tuple[jelly.RdfStreamRow] = ()
|
|
87
143
|
|
|
@@ -129,6 +185,19 @@ def encode_statement(
|
|
|
129
185
|
term_encoder: TermEncoder,
|
|
130
186
|
repeated_terms: dict[Slot, object],
|
|
131
187
|
) -> tuple[list[jelly.RdfStreamRow], dict[str, Any]]:
|
|
188
|
+
"""
|
|
189
|
+
Encode a statement.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
terms (Iterable[object]): original terms to encode
|
|
193
|
+
term_encoder (TermEncoder): encoder with lookup tables
|
|
194
|
+
repeated_terms (dict[Slot, object]): dictionary of repeated terms.
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
tuple[list[jelly.RdfStreamRow], dict[str, Any]]:
|
|
198
|
+
extra rows to append and jelly terms.
|
|
199
|
+
|
|
200
|
+
"""
|
|
132
201
|
statement: dict[str, object] = {}
|
|
133
202
|
rows: list[jelly.RdfStreamRow] = []
|
|
134
203
|
for slot, term in zip(Slot, terms):
|
|
@@ -147,6 +216,18 @@ def encode_triple(
|
|
|
147
216
|
term_encoder: TermEncoder,
|
|
148
217
|
repeated_terms: dict[Slot, object],
|
|
149
218
|
) -> list[jelly.RdfStreamRow]:
|
|
219
|
+
"""
|
|
220
|
+
Encode one triple.
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
terms (Iterable[object]): original terms to encode
|
|
224
|
+
term_encoder (TermEncoder): current encoder with lookup tables
|
|
225
|
+
repeated_terms (dict[Slot, object]): dictionary of repeated terms.
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
list[jelly.RdfStreamRow]: list of rows to add to the current flow.
|
|
229
|
+
|
|
230
|
+
"""
|
|
150
231
|
rows, statement = encode_statement(terms, term_encoder, repeated_terms)
|
|
151
232
|
row = jelly.RdfStreamRow(triple=jelly.RdfTriple(**statement))
|
|
152
233
|
rows.append(row)
|
|
@@ -158,6 +239,18 @@ def encode_quad(
|
|
|
158
239
|
term_encoder: TermEncoder,
|
|
159
240
|
repeated_terms: dict[Slot, object],
|
|
160
241
|
) -> list[jelly.RdfStreamRow]:
|
|
242
|
+
"""
|
|
243
|
+
Encode one quad.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
terms (Iterable[object]): original terms to encode
|
|
247
|
+
term_encoder (TermEncoder): current encoder with lookup tables
|
|
248
|
+
repeated_terms (dict[Slot, object]): dictionary of repeated terms.
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
list[jelly.RdfStreamRow]: list of messages to append to current flow.
|
|
252
|
+
|
|
253
|
+
"""
|
|
161
254
|
rows, statement = encode_statement(terms, term_encoder, repeated_terms)
|
|
162
255
|
row = jelly.RdfStreamRow(quad=jelly.RdfQuad(**statement))
|
|
163
256
|
rows.append(row)
|
|
@@ -169,6 +262,18 @@ def encode_namespace_declaration(
|
|
|
169
262
|
value: str,
|
|
170
263
|
term_encoder: TermEncoder,
|
|
171
264
|
) -> list[jelly.RdfStreamRow]:
|
|
265
|
+
"""
|
|
266
|
+
Encode namespace declaration.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
name (str): namespace prefix label
|
|
270
|
+
value (str): namespace iri
|
|
271
|
+
term_encoder (TermEncoder): current encoder
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
list[jelly.RdfStreamRow]: list of messages to append to current flow.
|
|
275
|
+
|
|
276
|
+
"""
|
|
172
277
|
[*rows], iri = term_encoder.encode_iri(value)
|
|
173
278
|
declaration = jelly.RdfNamespaceDeclaration(name=name, value=iri)
|
|
174
279
|
row = jelly.RdfStreamRow(namespace=declaration)
|
|
@@ -181,6 +286,18 @@ def encode_options(
|
|
|
181
286
|
stream_types: options.StreamTypes,
|
|
182
287
|
params: options.StreamParameters,
|
|
183
288
|
) -> jelly.RdfStreamRow:
|
|
289
|
+
"""
|
|
290
|
+
Encode stream options to ProtoBuf message.
|
|
291
|
+
|
|
292
|
+
Args:
|
|
293
|
+
lookup_preset (options.LookupPreset): lookup tables options
|
|
294
|
+
stream_types (options.StreamTypes): physical and logical types
|
|
295
|
+
params (options.StreamParameters): other params.
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
jelly.RdfStreamRow: encoded stream options row
|
|
299
|
+
|
|
300
|
+
"""
|
|
184
301
|
return jelly.RdfStreamRow(
|
|
185
302
|
options=jelly.RdfStreamOptions(
|
|
186
303
|
stream_name=params.stream_name,
|
pyjelly/serialize/flows.py
CHANGED
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from collections import UserList
|
|
4
4
|
from collections.abc import Iterable
|
|
5
5
|
from dataclasses import dataclass
|
|
6
|
-
from typing import ClassVar
|
|
6
|
+
from typing import Any, ClassVar
|
|
7
7
|
from typing_extensions import override
|
|
8
8
|
|
|
9
9
|
from pyjelly import jelly
|
|
@@ -16,11 +16,24 @@ class FrameFlow(UserList[jelly.RdfStreamRow]):
|
|
|
16
16
|
Abstract base class for producing Jelly frames from RDF stream rows.
|
|
17
17
|
|
|
18
18
|
Collects stream rows and assembles them into RdfStreamFrame objects when ready.
|
|
19
|
+
|
|
20
|
+
Allows for passing LogicalStreamType, required for
|
|
21
|
+
logical subtypes and non-delimited streams.
|
|
19
22
|
"""
|
|
20
23
|
|
|
21
24
|
logical_type: jelly.LogicalStreamType
|
|
22
25
|
registry: ClassVar[dict[jelly.LogicalStreamType, type[FrameFlow]]] = {}
|
|
23
26
|
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
initlist: Iterable[jelly.RdfStreamRow] | None = None,
|
|
30
|
+
*,
|
|
31
|
+
logical_type: jelly.LogicalStreamType | None = None,
|
|
32
|
+
**__kwargs: Any,
|
|
33
|
+
) -> None:
|
|
34
|
+
super().__init__(initlist)
|
|
35
|
+
self.logical_type = logical_type or self.__class__.logical_type
|
|
36
|
+
|
|
24
37
|
def frame_from_graph(self) -> jelly.RdfStreamFrame | None:
|
|
25
38
|
"""
|
|
26
39
|
Treat the current rows as a graph and produce a frame.
|
|
@@ -41,6 +54,16 @@ class FrameFlow(UserList[jelly.RdfStreamRow]):
|
|
|
41
54
|
return None
|
|
42
55
|
|
|
43
56
|
def to_stream_frame(self) -> jelly.RdfStreamFrame | None:
|
|
57
|
+
"""
|
|
58
|
+
Create stream frame from flow content.
|
|
59
|
+
|
|
60
|
+
Notes:
|
|
61
|
+
Clears flow content after creating the frame.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
jelly.RdfStreamFrame | None: stream frame
|
|
65
|
+
|
|
66
|
+
"""
|
|
44
67
|
if not self:
|
|
45
68
|
return None
|
|
46
69
|
frame = jelly.RdfStreamFrame(rows=self)
|
|
@@ -61,20 +84,11 @@ class ManualFrameFlow(FrameFlow):
|
|
|
61
84
|
|
|
62
85
|
logical_type = jelly.LOGICAL_STREAM_TYPE_UNSPECIFIED
|
|
63
86
|
|
|
64
|
-
def __init__(
|
|
65
|
-
self,
|
|
66
|
-
initlist: Iterable[jelly.RdfStreamRow] | None = None,
|
|
67
|
-
*,
|
|
68
|
-
logical_type: jelly.LogicalStreamType = jelly.LOGICAL_STREAM_TYPE_UNSPECIFIED,
|
|
69
|
-
) -> None:
|
|
70
|
-
super().__init__(initlist)
|
|
71
|
-
self.logical_type = logical_type
|
|
72
|
-
|
|
73
87
|
|
|
74
88
|
@dataclass
|
|
75
89
|
class BoundedFrameFlow(FrameFlow):
|
|
76
90
|
"""
|
|
77
|
-
|
|
91
|
+
Produce frames automatically when a fixed number of rows is reached.
|
|
78
92
|
|
|
79
93
|
Used for delimited encoding (default mode).
|
|
80
94
|
"""
|
|
@@ -82,17 +96,26 @@ class BoundedFrameFlow(FrameFlow):
|
|
|
82
96
|
logical_type = jelly.LOGICAL_STREAM_TYPE_UNSPECIFIED
|
|
83
97
|
frame_size: int
|
|
84
98
|
|
|
99
|
+
@override
|
|
85
100
|
def __init__(
|
|
86
101
|
self,
|
|
87
102
|
initlist: Iterable[jelly.RdfStreamRow] | None = None,
|
|
103
|
+
logical_type: jelly.LogicalStreamType | None = None,
|
|
88
104
|
*,
|
|
89
105
|
frame_size: int | None = None,
|
|
90
106
|
) -> None:
|
|
91
|
-
super().__init__(initlist)
|
|
107
|
+
super().__init__(initlist, logical_type=logical_type)
|
|
92
108
|
self.frame_size = frame_size or DEFAULT_FRAME_SIZE
|
|
93
109
|
|
|
94
110
|
@override
|
|
95
111
|
def frame_from_bounds(self) -> jelly.RdfStreamFrame | None:
|
|
112
|
+
"""
|
|
113
|
+
Emit frame from flow if full.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
jelly.RdfStreamFrame | None: stream frame
|
|
117
|
+
|
|
118
|
+
"""
|
|
96
119
|
if len(self) >= self.frame_size:
|
|
97
120
|
return self.to_stream_frame()
|
|
98
121
|
return None
|
|
@@ -110,6 +133,14 @@ class GraphsFrameFlow(FrameFlow):
|
|
|
110
133
|
logical_type = jelly.LOGICAL_STREAM_TYPE_GRAPHS
|
|
111
134
|
|
|
112
135
|
def frame_from_graph(self) -> jelly.RdfStreamFrame | None:
|
|
136
|
+
"""
|
|
137
|
+
Emit current flow content (one graph) as jelly frame.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
jelly.RdfStreamFrame | None: jelly frame or none if
|
|
141
|
+
flow is empty.
|
|
142
|
+
|
|
143
|
+
"""
|
|
113
144
|
return self.to_stream_frame()
|
|
114
145
|
|
|
115
146
|
|
|
@@ -117,6 +148,14 @@ class DatasetsFrameFlow(FrameFlow):
|
|
|
117
148
|
logical_type = jelly.LOGICAL_STREAM_TYPE_DATASETS
|
|
118
149
|
|
|
119
150
|
def frame_from_dataset(self) -> jelly.RdfStreamFrame | None:
|
|
151
|
+
"""
|
|
152
|
+
Emit current flow content (dataset) as jelly frame.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
jelly.RdfStreamFrame | None: jelly frame or none if
|
|
156
|
+
flow is empty.
|
|
157
|
+
|
|
158
|
+
"""
|
|
120
159
|
return self.to_stream_frame()
|
|
121
160
|
|
|
122
161
|
|
|
@@ -129,8 +168,26 @@ FLOW_DISPATCH: dict[jelly.LogicalStreamType, type[FrameFlow]] = {
|
|
|
129
168
|
|
|
130
169
|
|
|
131
170
|
def flow_for_type(logical_type: jelly.LogicalStreamType) -> type[FrameFlow]:
|
|
171
|
+
"""
|
|
172
|
+
Return flow based on logical type requested.
|
|
173
|
+
|
|
174
|
+
Note: uses base logical type for subtypes (i.e., SUBJECT_GRAPHS uses
|
|
175
|
+
the same flow as its base type GRAPHS).
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
logical_type (jelly.LogicalStreamType): logical type requested.
|
|
179
|
+
|
|
180
|
+
Raises:
|
|
181
|
+
NotImplementedError: if (base) logical stream type is not supported.
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
type[FrameFlow]: FrameFlow for respective logical type.
|
|
185
|
+
|
|
186
|
+
"""
|
|
132
187
|
try:
|
|
133
|
-
|
|
188
|
+
base_logical_type_value = logical_type % 10
|
|
189
|
+
base_name = jelly.LogicalStreamType.Name(base_logical_type_value)
|
|
190
|
+
return FLOW_DISPATCH[getattr(jelly.LogicalStreamType, base_name)]
|
|
134
191
|
except KeyError:
|
|
135
192
|
msg = (
|
|
136
193
|
"unsupported logical stream type: "
|
pyjelly/serialize/streams.py
CHANGED
|
@@ -60,6 +60,13 @@ class Stream:
|
|
|
60
60
|
)
|
|
61
61
|
|
|
62
62
|
def infer_flow(self) -> FrameFlow:
|
|
63
|
+
"""
|
|
64
|
+
Return flow based on the stream options provided.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
FrameFlow: initialised FrameFlow object.
|
|
68
|
+
|
|
69
|
+
"""
|
|
63
70
|
flow: FrameFlow
|
|
64
71
|
if self.options.params.delimited:
|
|
65
72
|
if self.options.logical_type != jelly.LOGICAL_STREAM_TYPE_UNSPECIFIED:
|
|
@@ -71,19 +78,24 @@ class Stream:
|
|
|
71
78
|
jelly.LOGICAL_STREAM_TYPE_FLAT_TRIPLES,
|
|
72
79
|
jelly.LOGICAL_STREAM_TYPE_FLAT_QUADS,
|
|
73
80
|
):
|
|
74
|
-
flow = flow_class(
|
|
81
|
+
flow = flow_class(
|
|
82
|
+
logical_type=self.options.logical_type,
|
|
83
|
+
frame_size=self.options.frame_size,
|
|
84
|
+
)
|
|
75
85
|
else:
|
|
76
|
-
flow = flow_class()
|
|
86
|
+
flow = flow_class(logical_type=self.options.logical_type)
|
|
77
87
|
else:
|
|
78
88
|
flow = ManualFrameFlow(logical_type=self.options.logical_type)
|
|
79
89
|
return flow
|
|
80
90
|
|
|
81
91
|
def enroll(self) -> None:
|
|
92
|
+
"""Initialize start of the stream."""
|
|
82
93
|
if not self.enrolled:
|
|
83
94
|
self.stream_options()
|
|
84
95
|
self.enrolled = True
|
|
85
96
|
|
|
86
97
|
def stream_options(self) -> None:
|
|
98
|
+
"""Encode and append stream options row to the current flow."""
|
|
87
99
|
self.flow.append(
|
|
88
100
|
encode_options(
|
|
89
101
|
stream_types=self.stream_types,
|
|
@@ -93,6 +105,14 @@ class Stream:
|
|
|
93
105
|
)
|
|
94
106
|
|
|
95
107
|
def namespace_declaration(self, name: str, iri: str) -> None:
|
|
108
|
+
"""
|
|
109
|
+
Add namespace declaration to jelly stream.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
name (str): namespace prefix label
|
|
113
|
+
iri (str): namespace iri
|
|
114
|
+
|
|
115
|
+
"""
|
|
96
116
|
rows = encode_namespace_declaration(
|
|
97
117
|
name=name,
|
|
98
118
|
value=iri,
|
|
@@ -102,6 +122,20 @@ class Stream:
|
|
|
102
122
|
|
|
103
123
|
@classmethod
|
|
104
124
|
def for_rdflib(cls, options: SerializerOptions | None = None) -> Stream:
|
|
125
|
+
"""
|
|
126
|
+
Initialize stream with RDFLib encoder.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
options (SerializerOptions | None, optional): Stream options.
|
|
130
|
+
Defaults to None.
|
|
131
|
+
|
|
132
|
+
Raises:
|
|
133
|
+
TypeError: if Stream is passed, and not a Stream for specific physical type.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Stream: initialized stream with RDFLib encoder.
|
|
137
|
+
|
|
138
|
+
"""
|
|
105
139
|
if cls is Stream:
|
|
106
140
|
msg = "Stream is an abstract base class, use a subclass instead"
|
|
107
141
|
raise TypeError(msg)
|
|
@@ -117,6 +151,19 @@ class Stream:
|
|
|
117
151
|
|
|
118
152
|
|
|
119
153
|
def stream_for_type(physical_type: jelly.PhysicalStreamType) -> type[Stream]:
|
|
154
|
+
"""
|
|
155
|
+
Give a Stream based on physical type specified.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
physical_type (jelly.PhysicalStreamType): jelly stream physical type.
|
|
159
|
+
|
|
160
|
+
Raises:
|
|
161
|
+
NotImplementedError: if no stream for requested physical type is available.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
type[Stream]: jelly stream
|
|
165
|
+
|
|
166
|
+
"""
|
|
120
167
|
try:
|
|
121
168
|
stream_cls = STREAM_DISPATCH[physical_type]
|
|
122
169
|
except KeyError:
|
|
@@ -133,6 +180,21 @@ class TripleStream(Stream):
|
|
|
133
180
|
default_delimited_flow_class: ClassVar = FlatTriplesFrameFlow
|
|
134
181
|
|
|
135
182
|
def triple(self, terms: Iterable[object]) -> jelly.RdfStreamFrame | None:
|
|
183
|
+
"""
|
|
184
|
+
Process one triple to Protobuf messages.
|
|
185
|
+
|
|
186
|
+
Note:
|
|
187
|
+
Adds new rows to the current flow and returns StreamFrame if
|
|
188
|
+
frame size conditions are met.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
terms (Iterable[object]): RDF terms to encode.
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
jelly.RdfStreamFrame | None: stream frame if
|
|
195
|
+
flow supports frames slicing and current flow is full
|
|
196
|
+
|
|
197
|
+
"""
|
|
136
198
|
new_rows = encode_triple(
|
|
137
199
|
terms,
|
|
138
200
|
term_encoder=self.encoder,
|
|
@@ -147,6 +209,17 @@ class QuadStream(Stream):
|
|
|
147
209
|
default_delimited_flow_class: ClassVar = FlatQuadsFrameFlow
|
|
148
210
|
|
|
149
211
|
def quad(self, terms: Iterable[object]) -> jelly.RdfStreamFrame | None:
|
|
212
|
+
"""
|
|
213
|
+
Process one quad to Protobuf messages.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
terms (Iterable[object]): terms to encode.
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
jelly.RdfStreamFrame | None: stream frame if
|
|
220
|
+
flow supports frames slicing and current flow is full
|
|
221
|
+
|
|
222
|
+
"""
|
|
150
223
|
new_rows = encode_quad(
|
|
151
224
|
terms,
|
|
152
225
|
term_encoder=self.encoder,
|
|
@@ -165,6 +238,17 @@ class GraphStream(TripleStream):
|
|
|
165
238
|
graph_id: object,
|
|
166
239
|
graph: Iterable[Iterable[object]],
|
|
167
240
|
) -> Generator[jelly.RdfStreamFrame]:
|
|
241
|
+
"""
|
|
242
|
+
Process one graph into a sequence of jelly frames.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
graph_id (object): graph id (BN, Literal, iri, default)
|
|
246
|
+
graph (Iterable[Iterable[object]]): iterable of triples (graph's content)
|
|
247
|
+
|
|
248
|
+
Yields:
|
|
249
|
+
Generator[jelly.RdfStreamFrame]: jelly frames.
|
|
250
|
+
|
|
251
|
+
"""
|
|
168
252
|
[*graph_rows], graph_node = self.encoder.encode_any(graph_id, Slot.graph)
|
|
169
253
|
kw_name = f"{Slot.graph}_{self.encoder.TERM_ONEOF_NAMES[type(graph_node)]}"
|
|
170
254
|
kws: dict[Any, Any] = {kw_name: graph_node}
|
|
@@ -172,7 +256,7 @@ class GraphStream(TripleStream):
|
|
|
172
256
|
graph_rows.append(start_row)
|
|
173
257
|
self.flow.extend(graph_rows)
|
|
174
258
|
for triple in graph:
|
|
175
|
-
if frame := self.triple(triple):
|
|
259
|
+
if frame := self.triple(triple): # has frame slicing inside
|
|
176
260
|
yield frame
|
|
177
261
|
end_row = jelly.RdfStreamRow(graph_end=jelly.RdfGraphEnd())
|
|
178
262
|
self.flow.append(end_row)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyjelly
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Jelly-RDF implementation for Python
|
|
5
5
|
Project-URL: Homepage, https://w3id.org/jelly/pyjelly
|
|
6
6
|
Project-URL: Documentation, https://w3id.org/jelly/pyjelly
|
|
@@ -28,7 +28,7 @@ Classifier: Topic :: File Formats
|
|
|
28
28
|
Classifier: Topic :: Software Development :: Libraries
|
|
29
29
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
30
30
|
Requires-Python: >=3.9
|
|
31
|
-
Requires-Dist: protobuf>=
|
|
31
|
+
Requires-Dist: protobuf>=6.30.0
|
|
32
32
|
Requires-Dist: typing-extensions>=4.12.2
|
|
33
33
|
Provides-Extra: rdflib
|
|
34
34
|
Requires-Dist: rdflib>=7.1.4; extra == 'rdflib'
|
|
@@ -50,13 +50,13 @@ Description-Content-Type: text/markdown
|
|
|
50
50
|
|
|
51
51
|
## Getting started
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
Install pyjelly from **[PyPI](https://pypi.org/project/pyjelly/)**:
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
56
|
pip install pyjelly[rdflib]
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
To write an RDF graph to a Jelly file
|
|
59
|
+
To write an RDF graph to a Jelly file:
|
|
60
60
|
|
|
61
61
|
```python
|
|
62
62
|
from rdflib import Graph
|
|
@@ -66,7 +66,7 @@ g.parse("http://xmlns.com/foaf/spec/index.rdf")
|
|
|
66
66
|
g.serialize(destination="foaf.jelly", format="jelly")
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
To read a Jelly file and convert it to an rdflib Graph
|
|
69
|
+
To read a Jelly file and convert it to an rdflib `Graph`:
|
|
70
70
|
|
|
71
71
|
```python
|
|
72
72
|
from rdflib import Graph
|
|
@@ -75,19 +75,19 @@ g = Graph()
|
|
|
75
75
|
g.parse("foaf.jelly", format="jelly")
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
**See
|
|
78
|
+
**See [our documentation](https://w3id.org/jelly/pyjelly) for [further examples](https://w3id.org/jelly/pyjelly/dev/getting-started/), a full [API reference](https://w3id.org/jelly/pyjelly/dev/api), and more.**
|
|
79
79
|
|
|
80
80
|
## Contributing and support
|
|
81
81
|
|
|
82
82
|
This project is being actively developed – you can stay tuned by [watching this repository](https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/about-notifications#subscription-options).
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
Join the **[Jelly Discord chat](https://discord.gg/A8sN5XwVa5)** to ask questions about pyjelly and to be up-to-date with the development activities.
|
|
85
85
|
|
|
86
86
|
### Commercial support
|
|
87
87
|
|
|
88
88
|
**[NeverBlink](https://neverblink.eu)** provides commercial support services for Jelly, including implementing custom features, system integrations, implementations for new frameworks, benchmarking, and more.
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
### Contributing
|
|
91
91
|
|
|
92
92
|
If you'd like to contribute, check out our [contributing guidelines](CONTRIBUTING.md).
|
|
93
93
|
|
|
@@ -6,23 +6,23 @@ pyjelly/_proto/patch.proto,sha256=gASUm0xDG9J1advNoq_cCsJYxudTbQaiZQBq4oW3kw4,52
|
|
|
6
6
|
pyjelly/_proto/rdf.proto,sha256=EKxyG421B4m0Wx5-6jjojdga_hA3jpZfF6-T3lMc0hI,12763
|
|
7
7
|
pyjelly/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
8
|
pyjelly/integrations/rdflib/__init__.py,sha256=lpIz6iildMf5bDvj3aBqZJ7kgKFrTx_tsqSb6PkLis0,552
|
|
9
|
-
pyjelly/integrations/rdflib/parse.py,sha256=
|
|
10
|
-
pyjelly/integrations/rdflib/serialize.py,sha256=
|
|
9
|
+
pyjelly/integrations/rdflib/parse.py,sha256=_H4f5qUU0IvMPaq1Tnm2UF1aXX-DY1qPn_7GmoIa4V0,13717
|
|
10
|
+
pyjelly/integrations/rdflib/serialize.py,sha256=etFY10HjmsjmuR6BjvWw32f2zBThW26mTGFn67jcOdc,9524
|
|
11
11
|
pyjelly/jelly/__init__.py,sha256=9kacwn8Ew_1fcgj1abz6miEz-AtUdPT2ltFWaRIE5VE,126
|
|
12
|
-
pyjelly/jelly/rdf_pb2.py,sha256=
|
|
13
|
-
pyjelly/jelly/rdf_pb2.pyi,sha256=-
|
|
12
|
+
pyjelly/jelly/rdf_pb2.py,sha256=qjgS3kQnCJqoOmgzvgk1BeYxGbeDX2zygJPc2vDjRts,8952
|
|
13
|
+
pyjelly/jelly/rdf_pb2.pyi,sha256=-gxZO-r2wyN68l83XomySz60c82SZmoPKh1HxamBjZs,11816
|
|
14
14
|
pyjelly/parse/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
-
pyjelly/parse/decode.py,sha256=
|
|
16
|
-
pyjelly/parse/ioutils.py,sha256=
|
|
15
|
+
pyjelly/parse/decode.py,sha256=ERgCLzBvbkJWTlg3RT0p-h8J60KNqpQ4mj_-JHoD7kg,13299
|
|
16
|
+
pyjelly/parse/ioutils.py,sha256=O3wRtL5tf1WyIZ1LTfHjHwjKEGrhIWqFisOWjYmspNg,3434
|
|
17
17
|
pyjelly/parse/lookup.py,sha256=1AbdZEycLC4tRfh3fgF5hv5PrhwhdWvCUC53iHt-E4c,2193
|
|
18
18
|
pyjelly/serialize/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
-
pyjelly/serialize/encode.py,sha256=
|
|
20
|
-
pyjelly/serialize/flows.py,sha256=
|
|
19
|
+
pyjelly/serialize/encode.py,sha256=WSeqxyBtxpMrWrefhnmNLf8ummzlT0rY7NKoUzFY8NQ,9498
|
|
20
|
+
pyjelly/serialize/flows.py,sha256=0C2soigJKyHr3xoR-7v0kc1RL8COwnuCRd4iVZpukFU,5524
|
|
21
21
|
pyjelly/serialize/ioutils.py,sha256=2_NaadLfHO3jKR1ZV7aK6jQ09sPKBar9iLFHYwourz8,400
|
|
22
22
|
pyjelly/serialize/lookup.py,sha256=h0lYFjdB6CIuN2DzAW6EE4ILJFUuto3paAK6DG1DZYg,4091
|
|
23
|
-
pyjelly/serialize/streams.py,sha256=
|
|
24
|
-
pyjelly-0.
|
|
25
|
-
pyjelly-0.
|
|
26
|
-
pyjelly-0.
|
|
27
|
-
pyjelly-0.
|
|
28
|
-
pyjelly-0.
|
|
23
|
+
pyjelly/serialize/streams.py,sha256=F_T3k9yLSPtUW2ZaL99hmjlPKmgG4nYNeNXUiee3jEY,8421
|
|
24
|
+
pyjelly-0.4.0.dist-info/METADATA,sha256=iLIzLhRWIN9fj1Fua45fBosWbLS1bQOnLZmVsGbfFQw,4607
|
|
25
|
+
pyjelly-0.4.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
26
|
+
pyjelly-0.4.0.dist-info/entry_points.txt,sha256=kUG0p9zso7HpitdMaQaXEj_KSqgOGsL0Ky9ARbecN1g,339
|
|
27
|
+
pyjelly-0.4.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
28
|
+
pyjelly-0.4.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|