From 41d79d734c45716199c591df6b3e641106920bcd Mon Sep 17 00:00:00 2001 From: Edmond Date: Tue, 26 Jul 2022 13:04:56 +0000 Subject: [PATCH] Add pyoxigraph type annotations for model module --- python/pyoxigraph/models.py | 242 ++++++++++++++++++++++++++++++++++++ python/src/model.rs | 14 +-- 2 files changed, 249 insertions(+), 7 deletions(-) create mode 100644 python/pyoxigraph/models.py diff --git a/python/pyoxigraph/models.py b/python/pyoxigraph/models.py new file mode 100644 index 00000000..5d190c14 --- /dev/null +++ b/python/pyoxigraph/models.py @@ -0,0 +1,242 @@ +from typing import Union + +from .pyoxigraph import NamedNode as PyNamedNode +from .pyoxigraph import BlankNode as PyBlankNode +from .pyoxigraph import Literal as PyLiteral +from .pyoxigraph import Triple as PyTriple +from .pyoxigraph import Quad as PyQuad +from .pyoxigraph import DefaultGraph as PyDefaultGraph + + +class NamedNode(PyNamedNode): + """An RDF `node identified by an IRI `_. + + :param value: the IRI as a string. + :raises ValueError: if the IRI is not valid according to `RFC 3987 `_. + + The :py:func:`str` function provides a serialization compatible with N-Triples, Turtle, and SPARQL: + + >>> str(NamedNode('http://example.com')) + '' + """ + + def __init__(self, value: str) -> None: + ... + + @property + def value(self) -> str: + """the named node IRI. + + >>> NamedNode("http://example.com").value + 'http://example.com' + """ + return super().value + + +class BlankNode(PyBlankNode): + """An RDF `blank node `_. + + :param value: the `blank node ID `_ (if not present, a random blank node ID is automatically generated). + :raises ValueError: if the blank node ID is invalid according to NTriples, Turtle, and SPARQL grammars. + + The :py:func:`str` function provides a serialization compatible with NTriples, Turtle, and SPARQL: + + >>> str(BlankNode('ex')) + '_:ex' + """ + + def __init__(self, value: Union[str, None] = None) -> None: + ... + + @property + def value(self) -> str: + """the `blank node ID `_. + + >>> BlankNode("ex").value + 'ex'""" + return super().value + + +class Literal(PyLiteral): + """An RDF `literal `_. + + :param value: the literal value or `lexical form `_. + :param datatype: the literal `datatype IRI `_. + :param language: the literal `language tag `_. + :raises ValueError: if the language tag is not valid according to `RFC 5646 `_ (`BCP 47 `_). + + The :py:func:`str` function provides a serialization compatible with NTriples, Turtle, and SPARQL: + + >>> str(Literal('example')) + '"example"' + >>> str(Literal('example', language='en')) + '"example"@en' + >>> str(Literal('11', datatype=NamedNode('http://www.w3.org/2001/XMLSchema#integer'))) + '"11"^^' + """ + + def __init__( + self, + value: str, + datatype: Union[NamedNode, None] = None, + language: Union[str, None] = None, + ) -> None: + ... + + @property + def datatype(self) -> NamedNode: + """the literal `datatype IRI `_. + + >>> Literal('11', datatype=NamedNode('http://www.w3.org/2001/XMLSchema#integer')).datatype + + >>> Literal('example').datatype + + >>> Literal('example', language='en').datatype + + """ + return super().datatype + + @property + def language(self) -> Union[str, None]: + """the literal `language tag `_. + + >>> Literal('example', language='en').language + 'en' + >>> Literal('example').language + """ + return super().language + + @property + def value(self) -> str: + """the literal value or `lexical form `_. + + >>> Literal("example").value + 'example' + """ + return super().value + + +class Triple(PyTriple): + """An RDF `triple `_. + + :param subject: the triple subject. + :param predicate: the triple predicate. + :param object: the triple object. + + The :py:func:`str` function provides a serialization compatible with NTriples, Turtle, and SPARQL: + + >>> str(Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'))) + ' "1"' + + A triple could also be easily destructed into its components: + + >>> (s, p, o) = Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1')) + """ + + def __init__( + self, + subject: Union[NamedNode, BlankNode, "Triple"], + predicate: NamedNode, + object: Union[NamedNode, BlankNode, Literal, "Triple"], + ) -> None: + ... + + @property + def subject(self) -> Union[NamedNode, BlankNode, "Triple"]: + """the triple subject. + + >>> Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1')).subject + + """ + return super().subject + + @property + def predicate(self) -> NamedNode: + """the triple predicate. + + >>> Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1')).predicate + + """ + return super().predicate + + @property + def object(self) -> Union[NamedNode, BlankNode, Literal, "Triple"]: + """the triple object. + + >>> Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1')).object + > + """ + return super().object + + +class Quad(PyQuad): + """ + An RDF `triple `_. + in a `RDF dataset `_. + + :param subject: the quad subject. + :param predicate: the quad predicate. + :param object: the quad object. + :param graph: the quad graph name. If not present, the default graph is assumed. + + The :py:func:`str` function provides a serialization compatible with NTriples, Turtle, and SPARQL: + + >>> str(Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g'))) + ' "1" ' + + >>> str(Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), DefaultGraph())) + ' "1"' + + A quad could also be easily destructed into its components: + + >>> (s, p, o, g) = Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')) + """ + + def __init__( + self, + subject: Union[NamedNode, BlankNode, Triple], + predicate: NamedNode, + object: Union[NamedNode, BlankNode, Literal, Triple], + graph: Union[NamedNode, BlankNode, "DefaultGraph", None] = None, + ) -> None: + ... + + @property + def subject(self) -> Union[NamedNode, BlankNode, Triple]: + """the quad subject. + + >>> Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')).subject + + """ + return super().subject + + @property + def predicate(self) -> NamedNode: + """the quad predicate. + + >>> Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')).predicate + + """ + return super().predicate + + @property + def object(self) -> Union[NamedNode, BlankNode, Literal, Triple]: + """the quad object. + + >>> Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')).object + > + """ + return super().object + + @property + def graph_name(self) -> Union[NamedNode, BlankNode, "DefaultGraph"]: + """the quad graph name. + + >>> Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')).graph_name + + """ + return super().graph_name + + +class DefaultGraph(PyDefaultGraph): + """The RDF `default graph name `_.""" diff --git a/python/src/model.rs b/python/src/model.rs index 5bc38d10..988cbeb7 100644 --- a/python/src/model.rs +++ b/python/src/model.rs @@ -19,7 +19,7 @@ use std::vec::IntoIter; /// /// >>> str(NamedNode('http://example.com')) /// '' -#[pyclass(name = "NamedNode", module = "oxigraph")] +#[pyclass(name = "NamedNode", module = "oxigraph", subclass)] #[pyo3(text_signature = "(value)")] #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)] pub struct PyNamedNode { @@ -121,7 +121,7 @@ impl PyNamedNode { /// /// >>> str(BlankNode('ex')) /// '_:ex' -#[pyclass(name = "BlankNode", module = "oxigraph")] +#[pyclass(name = "BlankNode", module = "oxigraph", subclass)] #[pyo3(text_signature = "(value)")] #[derive(Eq, PartialEq, Debug, Clone, Hash)] pub struct PyBlankNode { @@ -234,7 +234,7 @@ impl PyBlankNode { /// '"example"@en' /// >>> str(Literal('11', datatype=NamedNode('http://www.w3.org/2001/XMLSchema#integer'))) /// '"11"^^' -#[pyclass(name = "Literal", module = "oxigraph")] +#[pyclass(name = "Literal", module = "oxigraph", subclass)] #[pyo3(text_signature = "(value, *, datatype = None, language = None)")] #[derive(Eq, PartialEq, Debug, Clone, Hash)] pub struct PyLiteral { @@ -353,7 +353,7 @@ impl PyLiteral { } /// The RDF `default graph name `_. -#[pyclass(name = "DefaultGraph", module = "oxigraph")] +#[pyclass(name = "DefaultGraph", module = "oxigraph", subclass)] #[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)] pub struct PyDefaultGraph {} @@ -531,7 +531,7 @@ impl IntoPy for PyTerm { /// A triple could also be easily destructed into its components: /// /// >>> (s, p, o) = Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1')) -#[pyclass(name = "Triple", module = "oxigraph")] +#[pyclass(name = "Triple", module = "oxigraph", subclass)] #[derive(Eq, PartialEq, Debug, Clone, Hash)] #[pyo3(text_signature = "(subject, predicate, object)")] pub struct PyTriple { @@ -708,7 +708,7 @@ impl IntoPy for PyGraphName { /// A quad could also be easily destructed into its components: /// /// >>> (s, p, o, g) = Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')) -#[pyclass(name = "Quad", module = "oxigraph")] +#[pyclass(name = "Quad", module = "oxigraph", subclass)] #[pyo3(text_signature = "(subject, predicate, object, graph_name = None)")] #[derive(Eq, PartialEq, Debug, Clone, Hash)] pub struct PyQuad { @@ -870,7 +870,7 @@ impl PyQuad { /// /// >>> str(Variable('foo')) /// '?foo' -#[pyclass(name = "Variable", module = "oxigraph")] +#[pyclass(name = "Variable", module = "oxigraph", subclass)] #[pyo3(text_signature = "(value)")] #[derive(Eq, PartialEq, Debug, Clone, Hash)] pub struct PyVariable {