Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the property built-in as a decorator #1703

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 11 additions & 14 deletions rdflib/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,30 +350,27 @@ def __init__(
self.formula_aware = False
self.default_union = False

def __get_store(self):
@property
def store(self):
return self.__store

store = property(__get_store) # read-only attr

def __get_identifier(self):
@property
def identifier(self):
return self.__identifier

identifier = property(__get_identifier) # read-only attr

def _get_namespace_manager(self):
@property
def namespace_manager(self):
"""
this graph's namespace-manager
"""
if self.__namespace_manager is None:
self.__namespace_manager = NamespaceManager(self)
return self.__namespace_manager

def _set_namespace_manager(self, nm):
@namespace_manager.setter
def namespace_manager(self, nm):
self.__namespace_manager = nm

namespace_manager = property(
_get_namespace_manager,
_set_namespace_manager,
doc="this graph's namespace-manager",
)

def __repr__(self):
return "<Graph identifier=%s (%s)>" % (self.identifier, type(self))

Expand Down
13 changes: 7 additions & 6 deletions rdflib/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,24 +177,25 @@ def __init__(self, type_: str):
self.askAnswer: bool = None # type: ignore[assignment]
self.graph: "Graph" = None # type: ignore[assignment]

def _get_bindings(self):
@property
def bindings(self):
"""
a list of variable bindings as dicts
"""
if self._genbindings:
self._bindings += list(self._genbindings)
self._genbindings = None

return self._bindings

def _set_bindings(self, b):
@bindings.setter
def bindings(self, b):
if isinstance(b, (types.GeneratorType, itertools.islice)):
self._genbindings = b
self._bindings = []
else:
self._bindings = b

bindings = property(
_get_bindings, _set_bindings, doc="a list of variable bindings as dicts"
)

@staticmethod
def parse(
source=None,
Expand Down
8 changes: 6 additions & 2 deletions rdflib/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,13 @@ def __init__(self, graph, subject):
self._graph = graph
self._identifier = subject

graph = property(lambda self: self._graph)
@property
def graph(self):
return self._graph

identifier = property(lambda self: self._identifier)
@property
def identifier(self):
return self._identifier

def __hash__(self):
return hash(Resource) ^ hash(self._graph) ^ hash(self._identifier)
Expand Down
4 changes: 2 additions & 2 deletions rdflib/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ def __init__(self, configuration=None, identifier=None):
if configuration:
self.open(configuration)

def __get_node_pickler(self):
@property
def node_pickler(self):
if self.__node_pickler is None:
from rdflib.term import URIRef
from rdflib.term import BNode
Expand All @@ -169,7 +170,6 @@ def __get_node_pickler(self):
np.register(Variable, "V")
return self.__node_pickler

node_pickler = property(__get_node_pickler)

# Database management methods
def create(self, configuration):
Expand Down
11 changes: 10 additions & 1 deletion test/conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
from .earl import EarlReporter
import pytest

from rdflib import Graph

from .data import CONSISTENT_DATA_DIR
from .earl import EarlReporter

pytest_plugins = [EarlReporter.__module__]

# This is here so that asserts from these modules are formatted for human
# readibility.
pytest.register_assert_rewrite("test.testutils")


@pytest.fixture(scope="session")
def rdfs_graph() -> Graph:
return Graph().parse(CONSISTENT_DATA_DIR / "rdfs.ttl", format="turtle")
9 changes: 9 additions & 0 deletions test/consistent_test_data/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Consistent Test Data

This directory contains consistent graphs that can be used inside tests, the
graphs in this directory should not change.


## File origins

- `rdfs.ttl`: `http://www.w3.org/2000/01/rdf-schema#`
109 changes: 109 additions & 0 deletions test/consistent_test_data/rdfs.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .

<http://www.w3.org/2000/01/rdf-schema#> a owl:Ontology ;
dc:title "The RDF Schema vocabulary (RDFS)" .

rdfs:Resource a rdfs:Class ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:label "Resource" ;
rdfs:comment "The class resource, everything." .

rdfs:Class a rdfs:Class ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:label "Class" ;
rdfs:comment "The class of classes." ;
rdfs:subClassOf rdfs:Resource .

rdfs:subClassOf a rdf:Property ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:label "subClassOf" ;
rdfs:comment "The subject is a subclass of a class." ;
rdfs:range rdfs:Class ;
rdfs:domain rdfs:Class .

rdfs:subPropertyOf a rdf:Property ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:label "subPropertyOf" ;
rdfs:comment "The subject is a subproperty of a property." ;
rdfs:range rdf:Property ;
rdfs:domain rdf:Property .

rdfs:comment a rdf:Property ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:label "comment" ;
rdfs:comment "A description of the subject resource." ;
rdfs:domain rdfs:Resource ;
rdfs:range rdfs:Literal .

rdfs:label a rdf:Property ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:label "label" ;
rdfs:comment "A human-readable name for the subject." ;
rdfs:domain rdfs:Resource ;
rdfs:range rdfs:Literal .

rdfs:domain a rdf:Property ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:label "domain" ;
rdfs:comment "A domain of the subject property." ;
rdfs:range rdfs:Class ;
rdfs:domain rdf:Property .

rdfs:range a rdf:Property ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:label "range" ;
rdfs:comment "A range of the subject property." ;
rdfs:range rdfs:Class ;
rdfs:domain rdf:Property .

rdfs:seeAlso a rdf:Property ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:label "seeAlso" ;
rdfs:comment "Further information about the subject resource." ;
rdfs:range rdfs:Resource ;
rdfs:domain rdfs:Resource .

rdfs:isDefinedBy a rdf:Property ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:subPropertyOf rdfs:seeAlso ;
rdfs:label "isDefinedBy" ;
rdfs:comment "The defininition of the subject resource." ;
rdfs:range rdfs:Resource ;
rdfs:domain rdfs:Resource .

rdfs:Literal a rdfs:Class ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:label "Literal" ;
rdfs:comment "The class of literal values, eg. textual strings and integers." ;
rdfs:subClassOf rdfs:Resource .

rdfs:Container a rdfs:Class ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:label "Container" ;
rdfs:subClassOf rdfs:Resource ;
rdfs:comment "The class of RDF containers." .

rdfs:ContainerMembershipProperty a rdfs:Class ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:label "ContainerMembershipProperty" ;
rdfs:comment """The class of container membership properties, rdf:_1, rdf:_2, ...,
all of which are sub-properties of 'member'.""" ;
rdfs:subClassOf rdf:Property .

rdfs:member a rdf:Property ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:label "member" ;
rdfs:comment "A member of the subject resource." ;
rdfs:domain rdfs:Resource ;
rdfs:range rdfs:Resource .

rdfs:Datatype a rdfs:Class ;
rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
rdfs:label "Datatype" ;
rdfs:comment "The class of RDF datatypes." ;
rdfs:subClassOf rdfs:Class .

<http://www.w3.org/2000/01/rdf-schema#> rdfs:seeAlso <http://www.w3.org/2000/01/rdf-schema-more> .
4 changes: 4 additions & 0 deletions test/data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from pathlib import Path

TEST_DIR = Path(__file__).parent
CONSISTENT_DATA_DIR = TEST_DIR / "consistent_test_data"
51 changes: 50 additions & 1 deletion test/test_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,62 @@
from rdflib import URIRef, Graph, plugin
from rdflib.exceptions import ParserError
from rdflib.plugin import PluginException
from rdflib.namespace import Namespace
from rdflib.namespace import Namespace, NamespaceManager

from pathlib import Path
from rdflib.store import Store
from rdflib.term import BNode

from test.testutils import GraphHelper


class TestGraphPT:
"""
``pytest`` based test class for `rdflib.graph.Graph`.

New tests should be added here.
"""

def test_property_store(self) -> None:
"""
The ``store`` property works correctly.
"""
graph = Graph()
assert isinstance(graph.store, Store)

def test_property_identifier_default(self) -> None:
"""
The default identifier for a graph is a `rdflib.term.BNode`.
"""
graph = Graph()
assert isinstance(graph.identifier, BNode)

def test_property_identifier(self) -> None:
"""
The ``identifier`` property works correctly.
"""
id = URIRef("example:a")
graph = Graph(identifier=id)
assert id == graph.identifier

def test_property_namespace_manager(self) -> None:
"""
The ``namespace_manager`` property works correctly.
"""
graph = Graph()
# check repeats as property is a signleton
assert isinstance(graph.namespace_manager, NamespaceManager)
assert isinstance(graph.namespace_manager, NamespaceManager)

new_nsm = NamespaceManager(graph)
new_nsm.reset()
new_nsm.bind("test", URIRef("example:test:"))
graph.namespace_manager = new_nsm
assert isinstance(graph.namespace_manager, NamespaceManager)
nss = list(graph.namespace_manager.namespaces())
assert ("test", URIRef("example:test:")) in nss


class GraphTestCase(unittest.TestCase):
store = "default"
tmppath = None
Expand Down
12 changes: 12 additions & 0 deletions test/test_resource.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from rdflib import Graph
from rdflib.resource import Resource
from rdflib.namespace import RDFS


def test_properties(rdfs_graph: Graph) -> None:
"""
The properties of a `rdflib.resource.Resource` work as expected.
"""
cres = Resource(rdfs_graph, RDFS.Container)
assert cres.graph is rdfs_graph
assert cres.identifier == RDFS.Container
45 changes: 45 additions & 0 deletions test/test_sparql.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,48 @@ def test_txtresult():
assert len(lines) == 3
vars_check = [Variable(var.strip()) for var in lines[0].split("|")]
assert vars_check == vars


def test_property_bindings(rdfs_graph: Graph) -> None:
"""
The ``bindings`` property of a `rdflib.query.Result` result works as expected.
"""
result = rdfs_graph.query(
"""
SELECT ?class ?label WHERE {
?class rdf:type rdfs:Class.
?class rdfs:label ?label.
} ORDER BY ?class
"""
)
expected_bindings = [
{
Variable('class'): RDFS.Class,
Variable('label'): Literal('Class'),
},
{
Variable('class'): RDFS.Container,
Variable('label'): Literal('Container'),
},
{
Variable('class'): RDFS.ContainerMembershipProperty,
Variable('label'): Literal('ContainerMembershipProperty'),
},
{
Variable('class'): RDFS.Datatype,
Variable('label'): Literal('Datatype'),
},
{
Variable('class'): RDFS.Literal,
Variable('label'): Literal('Literal'),
},
{
Variable('class'): RDFS.Resource,
Variable('label'): Literal('Resource'),
},
]

assert expected_bindings == result.bindings

result.bindings = []
assert [] == result.bindings