Skip to content

Commit efdd225

Browse files
committed
wip
1 parent e04386f commit efdd225

File tree

6 files changed

+148
-115
lines changed

6 files changed

+148
-115
lines changed

rdflib/graph.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from typing import (
2+
IO,
23
Any,
34
Iterable,
45
Optional,
@@ -15,7 +16,7 @@
1516
from rdflib.namespace import Namespace, RDF
1617
from rdflib import plugin, exceptions, query, namespace
1718
import rdflib.term
18-
from rdflib.term import BNode, Identifier, Node, URIRef, Literal, Genid
19+
from rdflib.term import BNode, Node, URIRef, Literal, Genid
1920
from rdflib.paths import Path
2021
from rdflib.store import Store
2122
from rdflib.serializer import Serializer
@@ -31,9 +32,11 @@
3132
import tempfile
3233
import pathlib
3334

34-
from io import BytesIO, BufferedIOBase
35+
from io import BufferedIOBase, BytesIO
3536
from urllib.parse import urlparse
3637

38+
from _types import BytesIOish
39+
3740
assert Literal # avoid warning
3841
assert Namespace # avoid warning
3942

@@ -1025,7 +1028,12 @@ def absolutize(self, uri, defrag=1):
10251028
# no destination and non-None positional encoding
10261029
@overload
10271030
def serialize(
1028-
self, destination: None, format: str, base: Optional[str], encoding: str, **args
1031+
self,
1032+
destination: None,
1033+
format: str,
1034+
base: Optional[str],
1035+
encoding: str,
1036+
**args,
10291037
) -> bytes:
10301038
...
10311039

@@ -1049,7 +1057,7 @@ def serialize(
10491057
destination: None = ...,
10501058
format: str = ...,
10511059
base: Optional[str] = ...,
1052-
encoding: None = None,
1060+
encoding: None = ...,
10531061
**args,
10541062
) -> str:
10551063
...
@@ -1070,10 +1078,10 @@ def serialize(
10701078
@overload
10711079
def serialize(
10721080
self,
1073-
destination: Optional[Union[str, BufferedIOBase, pathlib.PurePath]] = None,
1074-
format: str = "turtle",
1075-
base: Optional[str] = None,
1076-
encoding: Optional[str] = None,
1081+
destination: Optional[Union[str, BufferedIOBase, pathlib.PurePath]] = ...,
1082+
format: str = ...,
1083+
base: Optional[str] = ...,
1084+
encoding: Optional[str] = ...,
10771085
**args,
10781086
) -> Union[bytes, str, "Graph"]:
10791087
...
@@ -1091,10 +1099,10 @@ def serialize(
10911099
10921100
:param destination:
10931101
The destination to serialize the graph to. This can be a path as a
1094-
:class:`string` or :class:`~pathlib.PurePath` object, or it can be a
1095-
:class:`~io.BufferedIOBase` like object. If this parameter is not
1102+
:class:`str` or :class:`~pathlib.PurePath` object, or it can be a
1103+
:class:`~typing.IO[bytes]` like object. If this parameter is not
10961104
supplied the serialized graph will be returned.
1097-
:type destination: Optional[Union[str, io.BufferedIOBase, pathlib.PurePath]]
1105+
:type destination: Optional[Union[str, typing.IO[bytes], pathlib.PurePath]]
10981106
:param format:
10991107
The format that the output should be written in. This value
11001108
references a :class:`~rdflib.serializer.Serializer` plugin. Format
@@ -1124,7 +1132,7 @@ def serialize(
11241132
base = self.base
11251133

11261134
serializer = plugin.get(format, Serializer)(self)
1127-
stream: BufferedIOBase
1135+
stream: IO[bytes]
11281136
if destination is None:
11291137
stream = BytesIO()
11301138
if encoding is None:
@@ -1134,7 +1142,7 @@ def serialize(
11341142
serializer.serialize(stream, base=base, encoding=encoding, **args)
11351143
return stream.getvalue()
11361144
if hasattr(destination, "write"):
1137-
stream = cast(BufferedIOBase, destination)
1145+
stream = cast(IO[bytes], destination)
11381146
serializer.serialize(stream, base=base, encoding=encoding, **args)
11391147
else:
11401148
if isinstance(destination, pathlib.PurePath):

rdflib/plugins/serializers/turtle.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
from rdflib.exceptions import Error
1111
from rdflib.serializer import Serializer
1212
from rdflib.namespace import RDF, RDFS
13-
from io import BufferedIOBase, TextIOBase, TextIOWrapper
14-
from typing import Optional
13+
from io import BufferedIOBase, RawIOBase, TextIOBase, TextIOWrapper
14+
from typing import IO, Optional
1515

1616
__all__ = ["RecursiveSerializer", "TurtleSerializer"]
1717

@@ -45,7 +45,7 @@ class RecursiveSerializer(Serializer):
4545
maxDepth = 10
4646
indentString = " "
4747
roundtrip_prefixes = ()
48-
stream: TextIOBase
48+
stream: IO[str]
4949

5050
def __init__(self, store):
5151

@@ -170,7 +170,7 @@ def indent(self, modifier=0):
170170
return (self.depth + modifier) * self.indentString
171171

172172
def write(self, text: str):
173-
"""Write text in given encoding."""
173+
"""Write text"""
174174
self.stream.write(text)
175175

176176

@@ -186,7 +186,6 @@ class TurtleSerializer(RecursiveSerializer):
186186

187187
short_name = "turtle"
188188
indentString = " "
189-
stream: TextIOBase
190189

191190
def __init__(self, store):
192191
self._ns_rewrite = {}
@@ -236,10 +235,11 @@ def serialize(
236235
**args
237236
):
238237
self.reset()
238+
if encoding is not None:
239+
self.encoding = encoding
239240
self.stream = TextIOWrapper(
240-
stream, encoding, errors="replace", write_through=True
241+
stream, self.encoding, errors="replace", write_through=True
241242
)
242-
# self.encoding = encoding
243243
# if base is given here, use that, if not and a base is set for the graph use that
244244
if base is not None:
245245
self.base = base
@@ -264,7 +264,6 @@ def serialize(
264264
self.write("\n")
265265

266266
self.endDocument()
267-
# stream.write("\n".encode(encoding))
268267
self.stream.write("\n")
269268
self.base = None
270269
self.stream.flush()

rdflib/plugins/sparql/results/csvresults.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
import codecs
1111
import csv
12+
from io import BufferedIOBase, RawIOBase
13+
from typing import IO, Optional, Union, cast
1214

1315
from rdflib import Variable, BNode, URIRef, Literal
1416

@@ -61,17 +63,23 @@ def __init__(self, result):
6163
if result.type != "SELECT":
6264
raise Exception("CSVSerializer can only serialize select query results")
6365

64-
def serialize(self, stream, encoding="utf-8", **kwargs):
66+
def serialize(
67+
self,
68+
stream: Union[IO[bytes], IO[str]],
69+
encoding: Optional[str] = None,
70+
**kwargs
71+
):
6572

6673
# the serialiser writes bytes in the given encoding
6774
# in py3 csv.writer is unicode aware and writes STRINGS,
6875
# so we encode afterwards
6976

7077
import codecs
7178

72-
stream = codecs.getwriter(encoding)(stream)
79+
if isinstance(stream, RawIOBase) or isinstance(stream, BufferedIOBase): # type: ignore[unreachable]
80+
stream = codecs.getwriter(encoding)(stream) # type: ignore[unreachable]
7381

74-
out = csv.writer(stream, delimiter=self.delim)
82+
out = csv.writer(cast(IO[str], stream), delimiter=self.delim)
7583

7684
vs = [self.serializeTerm(v, encoding) for v in self.result.vars]
7785
out.writerow(vs)

rdflib/query.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
import warnings
66
import types
77
import pathlib
8-
from typing import Optional, Union, cast, overload
8+
from typing import IO, Optional, Union, cast, overload
99

10-
from io import BytesIO, BufferedIOBase
10+
from io import BytesIO
1111

1212
from urllib.parse import urlparse
1313

1414
__all__ = ["Processor", "Result", "ResultParser", "ResultSerializer", "ResultException"]
1515

16+
from _types import BytesIOish
1617

1718
class Processor(object):
1819
"""
@@ -257,7 +258,7 @@ def serialize(
257258
@overload
258259
def serialize(
259260
self,
260-
destination: Union[str, BufferedIOBase, pathlib.PurePath],
261+
destination: Optional[Union[str, pathlib.PurePath, BytesIOish]] = ...,
261262
encoding: Optional[str] = ...,
262263
format: Optional[str] = ...,
263264
**args,
@@ -268,7 +269,7 @@ def serialize(
268269
@overload
269270
def serialize(
270271
self,
271-
destination: Union[str, BufferedIOBase, pathlib.PurePath, None] = None,
272+
destination: Optional[Union[str, pathlib.PurePath, BytesIOish]] = ...,
272273
encoding: Optional[str] = None,
273274
format: Optional[str] = None,
274275
**args,
@@ -277,7 +278,7 @@ def serialize(
277278

278279
def serialize(
279280
self,
280-
destination: Optional[Union[str, BufferedIOBase, pathlib.PurePath]] = None,
281+
destination: Optional[Union[str, pathlib.PurePath, BytesIOish]] = None,
281282
encoding: Optional[str] = None,
282283
format: Optional[str] = None,
283284
**args,
@@ -287,10 +288,10 @@ def serialize(
287288
288289
:param destination:
289290
The destination to serialize the result to. This can be a path as a
290-
:class:`string` or :class:`~pathlib.PurePath` object, or it can be a
291-
:class:`~io.BufferedIOBase` like object. If this parameter is not
291+
:class:`str` or :class:`~pathlib.PurePath` object, or it can be a
292+
:class:`~typing.IO[bytes]` like object. If this parameter is not
292293
supplied the serialized result will be returned.
293-
:type destination: Optional[Union[str, io.BufferedIOBase, pathlib.PurePath]]
294+
:type destination: Optional[Union[str, typing.IO[bytes], pathlib.PurePath]]
294295
:param encoding: Encoding of output.
295296
:type encoding: Optional[str]
296297
:param format:
@@ -321,9 +322,9 @@ def serialize(
321322
from rdflib import plugin
322323

323324
if format is None:
324-
format = "csv"
325+
format = "txt"
325326
serializer = plugin.get(format, ResultSerializer)(self)
326-
stream: BufferedIOBase
327+
stream: IO[bytes]
327328
if destination is None:
328329
stream = BytesIO()
329330
if encoding is None:
@@ -337,7 +338,7 @@ def serialize(
337338
# serializer.serialize(stream2, encoding=encoding, **args)
338339
# return streamb.getvalue()
339340
if hasattr(destination, "write"):
340-
stream = cast(BufferedIOBase, destination)
341+
stream = cast(IO[bytes], destination)
341342
serializer.serialize(stream, encoding=encoding, **args)
342343
else:
343344
if isinstance(destination, pathlib.PurePath):
@@ -430,15 +431,26 @@ def __init__(self):
430431

431432
def parse(self, source, **kwargs):
432433
"""return a Result object"""
433-
raise NotImplementedError("A ResultParser must implement the parse method")
434+
pass # abstract
434435

435436

436437
class ResultSerializer(object):
437438
def __init__(self, result):
438439
self.result = result
439440

440-
def serialize(self, stream, encoding="utf-8", **kwargs):
441+
@overload
442+
def serialize(self, stream: IO[bytes], encoding: Optional[str] = ..., **kwargs):
443+
...
444+
445+
@overload
446+
def serialize(self, stream: IO[str], encoding: None = ..., **kwargs):
447+
...
448+
449+
def serialize(
450+
self,
451+
stream: Union[IO[bytes], IO[str]],
452+
encoding: Optional[str] = None,
453+
**kwargs,
454+
):
441455
"""return a string properly serialized"""
442-
raise NotImplementedError(
443-
"A ResultSerializer must implement the serialize method"
444-
)
456+
pass # abstract

rdflib/serializer.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
1111
"""
1212

13-
from typing import Optional
13+
from typing import IO, BinaryIO, Optional, Union
1414
from rdflib.term import URIRef
15-
from io import BufferedIOBase
15+
from io import BufferedIOBase, RawIOBase
1616

1717
__all__ = ["Serializer"]
1818

@@ -25,13 +25,12 @@ def __init__(self, store):
2525

2626
def serialize(
2727
self,
28-
stream: BufferedIOBase,
28+
stream: Union[RawIOBase, BufferedIOBase, IO[bytes]],
2929
base: Optional[str] = None,
3030
encoding: Optional[str] = None,
3131
**args
3232
) -> None:
3333
"""Abstract method"""
34-
raise NotImplementedError("Serializer must implement the serialize method")
3534

3635
def relativize(self, uri: str):
3736
base = self.base

0 commit comments

Comments
 (0)