Changeset - 165fc8ed28ab
[Not reviewed]
default
0 2 0
drewp@bigasterisk.com - 20 months ago 2023-05-23 23:26:32
drewp@bigasterisk.com
clearly this approach is wrong
2 files changed with 5 insertions and 0 deletions:
0 comments (0 inline, 0 general)
light9/typedgraph.py
Show inline comments
 
@@ -51,35 +51,37 @@ def _convLiteral(objType: Type[_ObjType]
 
                # e.g. user wants float and we have xsd:double
 
                return cast(objType, outType(x.toPython()))
 
    raise ConversionError
 

	
 

	
 
def typedValue(objType: Type[_ObjType], graph: EitherGraph, subj: Node, pred: URIRef) -> _ObjType:
 
    """graph.value(subj, pred) with a given return type.
 
    If objType is not an rdflib.Node, we toPython() the value.
 

	
 
    Allow objType to include None if you want a None return for not-found.
 
    """
 
    if objType is None:
 
        raise TypeError('must allow non-None result type')
 
    obj = graph.value(subj, pred)
 
    if obj is None:
 
        if _typeIncludes(objType, None):
 
            return cast(objType, None)
 
        raise ValueError(f'No obj for {subj=} {pred=}')
 

	
 
    ConvFrom: Type[Node] = type(obj)
 
    ConvTo = objType
 
    try:
 
        if ConvFrom == URIRef and _typeIncludes(ConvTo, URIRef):
 
            conv = obj
 
        elif ConvFrom == URIRef and issubclass(URIRef, ConvTo) and not issubclass(str, ConvTo):  # rewrite please
 
            conv = obj
 
        elif ConvFrom == BNode and issubclass(BNode, ConvTo):
 
            conv = obj
 
        elif ConvFrom == Literal:
 
            conv = _convLiteral(objType, cast(Literal, obj))
 
        else:
 
            raise ConversionError
 
    except ConversionError:
 
        raise ConversionError(f'graph contains {type(obj)}, caller requesting {objType}')
 
    # if objType is float and isinstance(conv, decimal.Decimal):
 
    #     conv = float(conv)
 
    return cast(objType, conv)
 
\ No newline at end of file
light9/typedgraph_test.py
Show inline comments
 
@@ -28,48 +28,51 @@ subj = L9['subj']
 

	
 
class TestTypeIncludes:
 

	
 
    def test_includesItself(self):
 
        assert _typeIncludes(str, str)
 

	
 
    def test_includesUnionMember(self):
 
        assert _typeIncludes(int | str, str)
 

	
 
    def test_notIncludes(self):
 
        assert not _typeIncludes(int | str, None)
 

	
 
    def test_explicitOptionalWorks(self):
 
        assert _typeIncludes(Optional[int], None)
 

	
 
    def test_3WayUnionWorks(self):
 
        assert _typeIncludes(int | str | float, int)
 

	
 

	
 
class TestTypedValueReturnsBasicTypes:
 

	
 
    def test_getsUri(self):
 
        assert typedValue(URIRef, g, subj, L9['uri']) == L9['c']
 

	
 
    def test_getsAsNode(self):
 
        assert typedValue(Node, g, subj, L9['uri']) == L9['c']
 

	
 
    def test_getsBNode(self):
 
        # this is unusual usage since users ought to always be able to replace BNode with URIRef
 
        assert typedValue(BNode, g, subj, L9['bnode']) == g.value(subj,  L9['bnode'])
 

	
 
    def test_getsBNodeAsNode(self):
 
        assert typedValue(Node, g, subj, L9['bnode']) == g.value(subj,  L9['bnode'])
 

	
 

	
 
    def test_getsNumerics(self):
 
        assert typedValue(float, g, subj, L9['int']) == 0
 
        assert typedValue(float, g, subj, L9['float1']) == 0
 
        assert typedValue(float, g, subj, L9['float2']) == 10
 
        assert typedValue(float, g, subj, L9['float3']) == 0.5
 

	
 
        assert typedValue(int, g, subj, L9['int']) == 0
 
        # These retrieve rdf floats that happen to equal
 
        # ints, but no one should be relying on that.
 
        with pytest.raises(ConversionError):
 
            typedValue(int, g, subj, L9['float1'])
 
        with pytest.raises(ConversionError):
 
            typedValue(int, g, subj, L9['float2'])
 
        with pytest.raises(ConversionError):
 
            typedValue(int, g, subj, L9['float3'])
 

	
0 comments (0 inline, 0 general)