69
69
)
70
70
71
71
import rdflib
72
+ import rdflib .util
72
73
from rdflib .compat import long_type
73
74
74
75
if TYPE_CHECKING :
@@ -598,7 +599,7 @@ class Literal(Identifier):
598
599
_value : Any
599
600
_language : Optional [str ]
600
601
# NOTE: _datatype should maybe be of type URIRef, and not optional.
601
- _datatype : Optional [str ]
602
+ _datatype : Optional [URIRef ]
602
603
_ill_typed : Optional [bool ]
603
604
__slots__ = ("_language" , "_datatype" , "_value" , "_ill_typed" )
604
605
@@ -624,7 +625,7 @@ def __new__(
624
625
if lang is not None and not _is_valid_langtag (lang ):
625
626
raise ValueError (f"'{ str (lang )} ' is not a valid language tag!" )
626
627
627
- if datatype :
628
+ if datatype is not None :
628
629
datatype = URIRef (datatype )
629
630
630
631
value = None
@@ -633,7 +634,7 @@ def __new__(
633
634
# create from another Literal instance
634
635
635
636
lang = lang or lexical_or_value .language
636
- if datatype :
637
+ if datatype is not None :
637
638
# override datatype
638
639
value = _castLexicalToPython (lexical_or_value , datatype )
639
640
else :
@@ -644,7 +645,7 @@ def __new__(
644
645
# passed a string
645
646
# try parsing lexical form of datatyped literal
646
647
value = _castLexicalToPython (lexical_or_value , datatype )
647
- if datatype and datatype in _toPythonMapping :
648
+ if datatype is not None and datatype in _toPythonMapping :
648
649
# datatype is a recognized datatype IRI:
649
650
# https://www.w3.org/TR/rdf11-concepts/#dfn-recognized-datatype-iris
650
651
dt_uri : URIRef = URIRef (datatype )
@@ -661,10 +662,12 @@ def __new__(
661
662
value = lexical_or_value
662
663
_value , _datatype = _castPythonToLiteral (lexical_or_value , datatype )
663
664
664
- datatype = datatype or _datatype
665
+ _datatype = None if _datatype is None else URIRef (_datatype )
666
+
667
+ datatype = rdflib .util ._coalesce (datatype , _datatype )
665
668
if _value is not None :
666
669
lexical_or_value = _value
667
- if datatype :
670
+ if datatype is not None :
668
671
lang = None
669
672
670
673
if isinstance (lexical_or_value , bytes ):
@@ -729,7 +732,7 @@ def language(self) -> Optional[str]:
729
732
return self ._language
730
733
731
734
@property
732
- def datatype (self ) -> Optional [str ]:
735
+ def datatype (self ) -> Optional [URIRef ]:
733
736
return self ._datatype
734
737
735
738
def __reduce__ (
@@ -743,7 +746,7 @@ def __reduce__(
743
746
def __getstate__ (self ) -> Tuple [None , Dict [str , Union [str , None ]]]:
744
747
return (None , dict (language = self .language , datatype = self .datatype ))
745
748
746
- def __setstate__ (self , arg : Tuple [Any , Dict [str , str ]]) -> None :
749
+ def __setstate__ (self , arg : Tuple [Any , Dict [str , Any ]]) -> None :
747
750
_ , d = arg
748
751
self ._language = d ["language" ]
749
752
self ._datatype = d ["datatype" ]
@@ -1096,8 +1099,8 @@ def __gt__(self, other: Any) -> bool:
1096
1099
1097
1100
# plain-literals and xsd:string literals
1098
1101
# are "the same"
1099
- dtself = self .datatype or _XSD_STRING
1100
- dtother = other .datatype or _XSD_STRING
1102
+ dtself = rdflib . util . _coalesce ( self .datatype , default = _XSD_STRING )
1103
+ dtother = rdflib . util . _coalesce ( other .datatype , default = _XSD_STRING )
1101
1104
1102
1105
if dtself != dtother :
1103
1106
if rdflib .DAWG_LITERAL_COLLATION :
@@ -1129,9 +1132,9 @@ def __gt__(self, other: Any) -> bool:
1129
1132
# same language, same lexical form, check real dt
1130
1133
# plain-literals come before xsd:string!
1131
1134
if self .datatype != other .datatype :
1132
- if not self .datatype :
1135
+ if self .datatype is None :
1133
1136
return False
1134
- elif not other .datatype :
1137
+ elif other .datatype is None :
1135
1138
return True
1136
1139
else :
1137
1140
return self .datatype > other .datatype
@@ -1186,7 +1189,7 @@ def _comparable_to(self, other: Any) -> bool:
1186
1189
rich-compare with this literal
1187
1190
"""
1188
1191
if isinstance (other , Literal ):
1189
- if self .datatype and other .datatype :
1192
+ if self .datatype is not None and other .datatype is not None :
1190
1193
# two datatyped literals
1191
1194
if (
1192
1195
self .datatype not in XSDToPython
@@ -1247,7 +1250,7 @@ def __hash__(self) -> int: # type: ignore[override]
1247
1250
# Directly accessing the member is faster than the property.
1248
1251
if self ._language :
1249
1252
res ^= hash (self ._language .lower ())
1250
- if self ._datatype :
1253
+ if self ._datatype is not None :
1251
1254
res ^= hash (self ._datatype )
1252
1255
return res
1253
1256
@@ -1342,8 +1345,8 @@ def eq(self, other: Any) -> bool:
1342
1345
if (self .language or "" ).lower () != (other .language or "" ).lower ():
1343
1346
return False
1344
1347
1345
- dtself = self .datatype or _XSD_STRING
1346
- dtother = other .datatype or _XSD_STRING
1348
+ dtself = rdflib . util . _coalesce ( self .datatype , default = _XSD_STRING )
1349
+ dtother = rdflib . util . _coalesce ( other .datatype , default = _XSD_STRING )
1347
1350
1348
1351
if dtself == _XSD_STRING and dtother == _XSD_STRING :
1349
1352
# string/plain literals, compare on lexical form
@@ -1556,7 +1559,7 @@ def _literal_n3(
1556
1559
1557
1560
datatype = self .datatype
1558
1561
quoted_dt = None
1559
- if datatype :
1562
+ if datatype is not None :
1560
1563
if qname_callback :
1561
1564
quoted_dt = qname_callback (datatype )
1562
1565
if not quoted_dt :
@@ -1906,16 +1909,18 @@ def _well_formed_negative_integer(lexical: Union[str, bytes], value: Any) -> boo
1906
1909
URIRef (_XSD_PFX + "token" ),
1907
1910
)
1908
1911
1912
+ _StrT = TypeVar ("_StrT" , bound = str )
1913
+
1909
1914
1910
1915
def _py2literal (
1911
1916
obj : Any ,
1912
1917
pType : Any , # noqa: N803
1913
1918
castFunc : Optional [Callable [[Any ], Any ]],
1914
- dType : Optional [str ],
1915
- ) -> Tuple [Any , Optional [str ]]:
1916
- if castFunc :
1919
+ dType : Optional [_StrT ],
1920
+ ) -> Tuple [Any , Optional [_StrT ]]:
1921
+ if castFunc is not None :
1917
1922
return castFunc (obj ), dType
1918
- elif dType :
1923
+ elif dType is not None :
1919
1924
return obj , dType
1920
1925
else :
1921
1926
return obj , None
@@ -2062,7 +2067,7 @@ def _reset_bindings() -> None:
2062
2067
2063
2068
2064
2069
def _castLexicalToPython ( # noqa: N802
2065
- lexical : Union [str , bytes ], datatype : Optional [str ]
2070
+ lexical : Union [str , bytes ], datatype : Optional [URIRef ]
2066
2071
) -> Any :
2067
2072
"""
2068
2073
Map a lexical form to the value-space for the given datatype
0 commit comments