Repository: RDFLib/rdflib

Issue:
Update Lexical-to-value mapping for xsd:boolean
Hi,
I think the function for evaluating literals with datatype ```xsd:boolean``` should be updated. 

https://github.com/RDFLib/rdflib/blob/5fa18be1231a5e4dfc86ec28f2f754158c6f6f0b/rdflib/term.py#L1484

Currently, any string which is not equal to "true" or "1" is mapped to "false". However, according to [the spec](https://www.w3.org/TR/xmlschema11-2/#boolean) the lexical space for  boolean is only "0", "1", "true", "false". As a result, in case any other lexical value occurs, the parser should raise an Error and not parse it to a Literal with value "false".


Comments:

Patch:
diff --git a/rdflib/term.py b/rdflib/term.py
index 3d290258..125210df 100644
--- a/rdflib/term.py
+++ b/rdflib/term.py
@@ -1383,6 +1383,16 @@ def _unhexlify(value):
         value = value.encode()
     return unhexlify(value)
 
+def _parseBoolean(value):
+    true_accepted_values = ['1', 'true']
+    false_accepted_values = ['0', 'false']
+    new_value = value.lower()
+    if new_value in true_accepted_values:
+        return True
+    if new_value not in false_accepted_values:
+        warnings.warn('Parsing weird boolean, % r does not map to True or False' % value, category = DeprecationWarning)
+    return False
+
 # Cannot import Namespace/XSD because of circular dependencies
 _XSD_PFX = 'http://www.w3.org/2001/XMLSchema#'
 _RDF_PFX = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
@@ -1552,7 +1562,7 @@ XSDToPython = {
     URIRef(_XSD_PFX + 'normalizedString'): None,
     URIRef(_XSD_PFX + 'token'): None,
     URIRef(_XSD_PFX + 'language'): None,
-    URIRef(_XSD_PFX + 'boolean'): lambda i: i.lower() == 'true',
+    URIRef(_XSD_PFX + 'boolean'): _parseBoolean,
     URIRef(_XSD_PFX + 'decimal'): Decimal,
     URIRef(_XSD_PFX + 'integer'): long_type,
     URIRef(_XSD_PFX + 'nonPositiveInteger'): int,


Test patch:
diff --git a/test/test_literal.py b/test/test_literal.py
index dae2d187..3ed62d11 100644
--- a/test/test_literal.py
+++ b/test/test_literal.py
@@ -1,7 +1,7 @@
 import unittest
 
 import rdflib  # needed for eval(repr(...)) below
-from rdflib.term import Literal, URIRef, _XSD_DOUBLE, bind
+from rdflib.term import Literal, URIRef, _XSD_DOUBLE, bind, _XSD_BOOLEAN
 from six import integer_types, PY3, string_types
 
 
@@ -100,6 +100,29 @@ class TestDoubleOutput(unittest.TestCase):
         out = vv._literal_n3(use_plain=True)
         self.assertTrue(out in ["8.8e-01", "0.88"], out)
 
+class TestParseBoolean(unittest.TestCase):
+    """confirms the fix for https://github.com/RDFLib/rdflib/issues/913"""
+    def testTrueBoolean(self):
+        test_value = Literal("tRue", datatype = _XSD_BOOLEAN)
+        self.assertTrue(test_value.value)
+        test_value = Literal("1",datatype = _XSD_BOOLEAN)
+        self.assertTrue(test_value.value)
+
+    def testFalseBoolean(self):
+        test_value = Literal("falsE", datatype = _XSD_BOOLEAN)
+        self.assertFalse(test_value.value)
+        test_value = Literal("0",datatype = _XSD_BOOLEAN)
+        self.assertFalse(test_value.value)
+
+    def testNonFalseBoolean(self):
+        test_value = Literal("abcd", datatype = _XSD_BOOLEAN)
+        self.assertRaises(DeprecationWarning)
+        self.assertFalse(test_value.value)
+        test_value = Literal("10",datatype = _XSD_BOOLEAN)
+        self.assertRaises(DeprecationWarning)
+        self.assertFalse(test_value.value)
+
+
 
 class TestBindings(unittest.TestCase):