Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 8 additions & 15 deletions rdflib/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,11 @@
_TripleOrQuadSelectorType = Union["_TripleSelectorType", "_QuadSelectorType"]
_TriplePathType = Tuple["_SubjectType", Path, "_ObjectType"]
_TripleOrTriplePathType = Union["_TripleType", "_TriplePathType"]
_TripleChoiceType = Union[
Tuple[List[_SubjectType], Optional[_PredicateType], Optional[_ObjectType]],
Tuple[Optional[_SubjectType], List[_PredicateType], Optional[_ObjectType]],
Tuple[Optional[_SubjectType], Optional[_PredicateType], List[_ObjectType]],
]

_GraphT = TypeVar("_GraphT", bound="Graph")
_ConjunctiveGraphT = TypeVar("_ConjunctiveGraphT", bound="ConjunctiveGraph")
Expand Down Expand Up @@ -994,11 +999,7 @@ def predicate_objects(

def triples_choices(
self,
triple: Union[
Tuple[List[_SubjectType], _PredicateType, _ObjectType],
Tuple[_SubjectType, List[_PredicateType], _ObjectType],
Tuple[_SubjectType, _PredicateType, List[_ObjectType]],
],
triple: _TripleChoiceType,
context: Optional[_ContextType] = None,
) -> Generator[_TripleType, None, None]:
subject, predicate, object_ = triple
Expand Down Expand Up @@ -2196,11 +2197,7 @@ def quads(

def triples_choices(
self,
triple: Union[
Tuple[List[_SubjectType], _PredicateType, _ObjectType],
Tuple[_SubjectType, List[_PredicateType], _ObjectType],
Tuple[_SubjectType, _PredicateType, List[_ObjectType]],
],
triple: _TripleChoiceType,
context: Optional[_ContextType] = None,
) -> Generator[_TripleType, None, None]:
"""Iterate over all the triples in the entire conjunctive graph"""
Expand Down Expand Up @@ -2946,11 +2943,7 @@ def __isub__(self: _GraphT, other: Iterable[_TripleType]) -> NoReturn:

def triples_choices(
self,
triple: Union[
Tuple[List[_SubjectType], _PredicateType, _ObjectType],
Tuple[_SubjectType, List[_PredicateType], _ObjectType],
Tuple[_SubjectType, _PredicateType, List[_ObjectType]],
],
triple: _TripleChoiceType,
context: Optional[_ContextType] = None,
) -> Generator[_TripleType, None, None]:
subject, predicate, object_ = triple
Expand Down
9 changes: 6 additions & 3 deletions rdflib/plugins/parsers/rdfxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,8 @@ def document_element_start(
self, name: Tuple[str, str], qname, attrs: AttributesImpl
) -> None:
if name[0] and URIRef("".join(name)) == RDFVOC.RDF:
next = self.next
# Cheap hack so 2to3 doesn't turn it into __next__
next = getattr(self, "next")
next.start = self.node_element_start
next.end = self.node_element_end
else:
Expand All @@ -315,7 +316,8 @@ def node_element_start(
current = self.current
absolutize = self.absolutize

next = self.next
# Cheap hack so 2to3 doesn't turn it into __next__
next = getattr(self, "next")
next.start = self.property_element_start
next.end = self.property_element_end

Expand Down Expand Up @@ -408,7 +410,8 @@ def property_element_start(
current = self.current
absolutize = self.absolutize

next = self.next
# Cheap hack so 2to3 doesn't turn it into __next__
next = getattr(self, "next")
object: Optional[_ObjectType] = None
current.data = None
current.list = None
Expand Down
43 changes: 33 additions & 10 deletions rdflib/plugins/serializers/longturtle.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,20 @@


class LongTurtleSerializer(RecursiveSerializer):
"""LongTurtle, a Turtle serialization format.

When the optional parameter ``canon`` is set to :py:obj:`True`, the graph is canonicalized
before serialization. This normalizes blank node identifiers and allows for
deterministic serialization of the graph. Useful when consistent outputs are required.
"""

short_name = "longturtle"
indentString = " "

def __init__(self, store):
self._ns_rewrite = {}
store = to_canonical_graph(store)
content = store.serialize(format="application/n-triples")
lines = content.split("\n")
lines.sort()
graph = Graph()
graph.parse(
data="\n".join(lines), format="application/n-triples", skolemize=True
)
graph = graph.de_skolemize()
super(LongTurtleSerializer, self).__init__(graph)
self._canon = False
super(LongTurtleSerializer, self).__init__(store)
self.keywords = {RDF.type: "a"}
self.reset()
self.stream = None
Expand Down Expand Up @@ -83,11 +82,34 @@ def addNamespace(self, prefix, namespace):
super(LongTurtleSerializer, self).addNamespace(prefix, namespace)
return prefix

def canonize(self):
"""Apply canonicalization to the store.

This normalizes blank node identifiers and allows for deterministic
serialization of the graph.
"""
if not self._canon:
return

namespace_manager = self.store.namespace_manager
store = to_canonical_graph(self.store)
content = store.serialize(format="application/n-triples")
lines = content.split("\n")
lines.sort()
graph = Graph()
graph.parse(
data="\n".join(lines), format="application/n-triples", skolemize=True
)
graph = graph.de_skolemize()
graph.namespace_manager = namespace_manager
self.store = graph

def reset(self):
super(LongTurtleSerializer, self).reset()
self._shortNames = {}
self._started = False
self._ns_rewrite = {}
self.canonize()

def serialize(
self,
Expand All @@ -97,6 +119,7 @@ def serialize(
spacious: Optional[bool] = None,
**kwargs: Any,
) -> None:
self._canon = kwargs.get("canon", False)
self.reset()
self.stream = stream
# if base is given here, use, if not and a base is set for the graph use that
Expand Down
89 changes: 69 additions & 20 deletions rdflib/plugins/shared/jsonld/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@
# https://github.com/RDFLib/rdflib-jsonld/blob/feature/json-ld-1.1/rdflib_jsonld/context.py
from __future__ import annotations

from collections import namedtuple
from collections.abc import Collection, Generator
from typing import (
TYPE_CHECKING,
Any,
Collection,
Dict,
Generator,
List,
NamedTuple,
Optional,
Set,
Tuple,
Expand Down Expand Up @@ -74,27 +73,47 @@ class Defined(int):


class Context:
"""
A JSON-LD context, which contains term definitions
"""

_base: str | None
#: _alias maps NODE_KEY to list of aliases
_alias: dict[str, list[str]]
_lookup: dict[tuple[str, Any, Defined | str, bool], Term]
_prefixes: dict[str, Any]
_context_cache: dict[str, Any]

version: float
language: str | None
doc_base: str | None
vocab: str | None
active: bool
propagate: bool
terms: dict[str, Any]
parent: Context | None

def __init__(
self,
source: _ContextSourceType = None,
base: Optional[str] = None,
version: Optional[float] = 1.1,
):
self.version: float = version or 1.1
self._alias = {}
self._lookup = {}
self._prefixes = {}
self._context_cache = {}

self.version = version or 1.1
self.language = None
self.vocab: Optional[str] = None
self._base: Optional[str]
self.base = base
self.doc_base = base
self.terms: Dict[str, Any] = {}
# _alias maps NODE_KEY to list of aliases
self._alias: Dict[str, List[str]] = {}
self._lookup: Dict[Tuple[str, Any, Union[Defined, str], bool], Term] = {}
self._prefixes: Dict[str, Any] = {}
self.active = False
self.parent: Optional[Context] = None
self.propagate = True
self._context_cache: Dict[str, Any] = {}
self.vocab = None
self.base = base
self.terms = {}
self.parent = None

if source:
self.load(source)

Expand Down Expand Up @@ -668,9 +687,39 @@ def to_dict(self) -> Dict[str, Any]:
return r


Term = namedtuple(
"Term",
"id, name, type, container, index, language, reverse, context," "prefix, protected",
)

Term.__new__.__defaults__ = (UNDEF, UNDEF, UNDEF, UNDEF, False, UNDEF, False, False)
class Term(NamedTuple):
"""
Describes how a JSON key should be interpreted when parsed as RDF
"""

#: The IRI or CURIE of the term.
id: str
#: The name of the term, ie an alias for the id.
name: str
#: The type of the term, such as @id, @json, @none or @vocab
type: Defined | str = UNDEF
#: The container type, such as @graph, @id, @index, @language, @list, @set or @type,
container: Collection[Any] | str | Defined = UNDEF
#: A predicate IRI that should be used to interpret keys of this object,
#: when used alongside `@container: @index`.
#: See https://www.w3.org/TR/json-ld11/#property-based-data-indexing
#: Ideally this wouldn't be called 'index' as it overrides the tuple's builtin index() method
#: Hence the pyright ignore comment
index: str | Defined | None = (
None # pyright: ignore[reportIncompatibleMethodOverride]
)
#: The language to be used for values of this term
language: str | Defined | None = UNDEF
#: Indicates that this term is a reverse property, so subject and object are swapped.
#: https://www.w3.org/TR/json-ld11/#reverse-properties
reverse: bool = False
#: A scoped context used inside values that use this term.
#: See https://www.w3.org/TR/json-ld11/#scoped-contexts
context: Any = UNDEF
#: If true, indicates that this should be used during compaction.
#: If false, indicates that this term cannot be used in compaction.
#: See https://www.w3.org/TR/json-ld11/#compact-iris
prefix: bool | None = None
#: If true, marks the term as protected, meaning it cannot be overridden by a subcontext.
#: See https://www.w3.org/TR/json-ld11/#protected-term-definitions
protected: bool = False
15 changes: 10 additions & 5 deletions rdflib/plugins/stores/berkeleydb.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,8 @@ def remove( # type: ignore[override]
cursor = index.cursor(txn=txn)
try:
cursor.set_range(key)
current = cursor.next
# Hack to stop 2to3 converting this to next(cursor)
current = getattr(cursor, "next")()
except db.DBNotFoundError:
current = None
cursor.close()
Expand Down Expand Up @@ -505,7 +506,8 @@ def triples(
cursor = index.cursor(txn=txn)
try:
cursor.set_range(key)
current = cursor.next
# Cheap hack so 2to3 doesn't convert to next(cursor)
current = getattr(cursor, "next")()
except db.DBNotFoundError:
current = None
cursor.close()
Expand Down Expand Up @@ -537,7 +539,8 @@ def __len__(self, context: Optional[_ContextType] = None) -> int:
key, value = current
if key.startswith(prefix):
count += 1
current = cursor.next
# Hack to stop 2to3 converting this to next(cursor)
current = getattr(cursor, "next")()
else:
break
cursor.close()
Expand Down Expand Up @@ -590,7 +593,8 @@ def namespaces(self) -> Generator[Tuple[str, URIRef], None, None]:
while current:
prefix, namespace = current
results.append((prefix.decode("utf-8"), namespace.decode("utf-8")))
current = cursor.next
# Hack to stop 2to3 converting this to next(cursor)
current = getattr(cursor, "next")()
cursor.close()
for prefix, namespace in results:
yield prefix, URIRef(namespace)
Expand Down Expand Up @@ -633,7 +637,8 @@ def contexts(
cursor = index.cursor()
try:
cursor.set_range(key)
current = cursor.next
# Hack to stop 2to3 converting this to next(cursor)
current = getattr(cursor, "next")()
except db.DBNotFoundError:
current = None
cursor.close()
Expand Down
7 changes: 2 additions & 5 deletions rdflib/plugins/stores/sparqlstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
_TripleType,
_ContextType,
_QuadType,
_TripleChoiceType,
_TriplePatternType,
_SubjectType,
_PredicateType,
Expand Down Expand Up @@ -367,11 +368,7 @@ def triples( # type: ignore[override]

def triples_choices(
self,
_: Tuple[
Union[_SubjectType, List[_SubjectType]],
Union[_PredicateType, List[_PredicateType]],
Union[_ObjectType, List[_ObjectType]],
],
_: _TripleChoiceType,
context: Optional[_ContextType] = None,
) -> Generator[
Tuple[
Expand Down
11 changes: 2 additions & 9 deletions rdflib/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
Generator,
Iterable,
Iterator,
List,
Mapping,
Optional,
Tuple,
Expand All @@ -49,10 +48,8 @@
from rdflib.graph import (
Graph,
_ContextType,
_ObjectType,
_PredicateType,
_QuadType,
_SubjectType,
_TripleChoiceType,
_TriplePatternType,
_TripleType,
)
Expand Down Expand Up @@ -281,11 +278,7 @@ def remove(

def triples_choices(
self,
triple: Union[
Tuple[List[_SubjectType], _PredicateType, _ObjectType],
Tuple[_SubjectType, List[_PredicateType], _ObjectType],
Tuple[_SubjectType, _PredicateType, List[_ObjectType]],
],
triple: _TripleChoiceType,
context: Optional[_ContextType] = None,
) -> Generator[
Tuple[
Expand Down
Loading
Loading