Skip to content

Commit 747b8d3

Browse files
edmondchucnicholascarddeschepperslahntgbugs
authored
[7.x] notation3.py: don't normalize float representation (#3221)
* 7.1.4 pre-release * fix namespace prefixes in longturtle serialization (#3134) Co-authored-by: Daan de Schepper <[email protected]> * Fix failing webtest (#3194) * test: fix failing webtest Fixes #3192 * Revert "remove old hacks against 2to3 (#3076)" (#3195) This reverts commit b74c657. * Specify `Optional` parameters in `Graph.triples_choices` (#3075) * Specify `Optional` parameters in `Graph.triples_choices` The two non-list parameters can be `None`, but this is not reflected in the type hint. Also introduces a type alias to simplify method signatures. * style: remove unused imports --------- Co-authored-by: Nicholas Car <[email protected]> Co-authored-by: Edmond Chuc <[email protected]> Co-authored-by: Edmond Chuc <[email protected]> * feat: canonicalization with longturtle serializer now optional (#3197) * feat: canonicalization with longturtle serializer now optional Fixes #3196 * docs: fix docs build error by removing py obj reference to canon * added n3 test to check for internal float normalization made as a separate commit to illustrate the old broken behavior priro to the fix in the next commit * notation3.py: don't normalize float representation fix behavior of the n3 parser family to avoid normalizing raw float string representation which makes it impossible to roundtrip the exact original string representation of e.g. 1e10 * test: refactor test_float_no_norm to use pytest parametrization * style: add noqa to sfloat class * chore: remove unused mypy type ignore * docs: fix sfloat reference * fix: sphinx nitpicky reference --------- Co-authored-by: Nicholas Car <[email protected]> Co-authored-by: Daan de Schepper <[email protected]> Co-authored-by: Sigmund Lahn <[email protected]> Co-authored-by: Nicholas Car <[email protected]> Co-authored-by: Tom Gillespie <[email protected]>
1 parent c580c00 commit 747b8d3

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

rdflib/plugins/parsers/notation3.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
"Formula",
8484
"RDFSink",
8585
"SinkParser",
86+
"sfloat",
8687
]
8788

8889
from rdflib.parser import Parser
@@ -380,6 +381,10 @@ def unicodeExpand(m: Match) -> str:
380381
langcode = re.compile(r"[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*")
381382

382383

384+
class sfloat(str): # noqa: N801
385+
"""don't normalize raw XSD.double string representation"""
386+
387+
383388
class SinkParser:
384389
def __init__(
385390
self,
@@ -1528,7 +1533,7 @@ def nodeOrLiteral(self, argstr: str, i: int, res: MutableSequence[Any]) -> int:
15281533
m = exponent_syntax.match(argstr, i)
15291534
if m:
15301535
j = m.end()
1531-
res.append(float(argstr[i:j]))
1536+
res.append(sfloat(argstr[i:j]))
15321537
return j
15331538

15341539
m = decimal_syntax.match(argstr, i)
@@ -1911,7 +1916,7 @@ def makeStatement(
19111916
def normalise(
19121917
self,
19131918
f: Optional[Formula],
1914-
n: Union[Tuple[int, str], bool, int, Decimal, float, _AnyT],
1919+
n: Union[Tuple[int, str], bool, int, Decimal, sfloat, _AnyT],
19151920
) -> Union[URIRef, Literal, BNode, _AnyT]:
19161921
if isinstance(n, tuple):
19171922
return URIRef(str(n[1]))
@@ -1931,7 +1936,7 @@ def normalise(
19311936
s = Literal(value, datatype=DECIMAL_DATATYPE)
19321937
return s
19331938

1934-
if isinstance(n, float):
1939+
if isinstance(n, sfloat):
19351940
s = Literal(str(n), datatype=DOUBLE_DATATYPE)
19361941
return s
19371942

@@ -1947,7 +1952,7 @@ def normalise(
19471952
# f.universals[n] = f.newBlankNode()
19481953
# return f.universals[n]
19491954
# type error: Incompatible return value type (got "Union[int, _AnyT]", expected "Union[URIRef, Literal, BNode, _AnyT]") [return-value]
1950-
return n # type: ignore[return-value]
1955+
return n
19511956

19521957
def intern(self, something: _AnyT) -> _AnyT:
19531958
return something

test/test_n3.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,23 @@ def test_empty_prefix(self):
251251
g2
252252
), "Document with declared empty prefix must match default #"
253253

254+
@pytest.mark.parametrize(
255+
"do_normalize_literal, expected_result",
256+
[(True, {"1.0", "10000000000.0"}), (False, {"1e10", "1e0"})],
257+
)
258+
def test_float_no_norm(self, do_normalize_literal, expected_result):
259+
import rdflib
260+
261+
original_normalize_literal = rdflib.NORMALIZE_LITERALS
262+
try:
263+
rdflib.NORMALIZE_LITERALS = do_normalize_literal
264+
g1 = Graph()
265+
g1.parse(data=":a :b 1e10, 1e0 .", format="n3")
266+
values = set(str(o) for o in g1.objects())
267+
assert values == expected_result
268+
finally:
269+
rdflib.NORMALIZE_LITERALS = original_normalize_literal
270+
254271

255272
class TestRegularExpressions:
256273
def test_exponents(self):

0 commit comments

Comments
 (0)