SuRF surf.resource.Resource objects are the core part of SuRF. In SuRF, RDF data is queried, accessed and modified by working with attributes of Resource objects. Here’s how the SuRF Resource maps to the RDF triples conceptual level:
If type and URI of resource is known, resource can be loaded using session’s surf.session.Session.get_class() and surf.session.Session.get_resource() methods:
# Create FoafPerson class:
FoafPerson = session.get_class(surf.ns.FOAF.Person)
# Create instance of FoafPerson class:
john = session.get_resource("http://john.com/me", FoafPerson)
# or simply like this
john = FoafPerson("http://john.com/me")
Getting all instances of FoafPerson class, in undefined order:
>>> FoafPerson = session.get_class(surf.ns.FOAF.Person)
>>> for person in FoafPerson.all():
... print "Found person:", person.foaf_name.first
Found person: ...
Found person: ...
Getting instances of FoafPerson class named “John”:
>>> FoafPerson = session.get_class(surf.ns.FOAF.Person)
>>> for person in FoafPerson.get_by(foaf_name = "John"):
... print "Found person:", person.foaf_name.first
Found person: John
Getting ordered and limited list of persons:
>>> FoafPerson = session.get_class(surf.ns.FOAF.Person)
>>> for person in FoafPerson.all().limit(10).order(surf.ns.FOAF.name):
... print "Found person:", person.foaf_name.first
Found person: Jane
Found person: John
Other modifiers accepted by all() and get_by are described in surf.resource.result_proxy module.
A SuRF resource represents a single RDF resource. Its URI is stored in subject attribute:
>>> FoafPerson = session.get_class(surf.ns.FOAF.Person)
>>> john = session.get_resource("http://john.com/me", FoafPerson)
>>> print john.subject
http://john.com/me
RDF triples that describe this resource are available as object attributes. SuRF follows “prefix_predicate” convention for attribute names. These attributes are instances of surf.resource.value.ResourceValue class. They are list-like, with some extra convenience functions:
>>> # Print all foaf:name values
>>> print john.foaf_name
[rdflib.Literal(u'John')]
>>> # Print first foaf:name value or None if there aren't any:
>>> print john.foaf_name.first
John
>>> # Print first foaf:name value or raise exception if there aren't any or
>>> # there are more than one:
>>> print john.foaf_nonexistant_predicate.one
Traceback (most recent call last):
...
NoResultFound: list is empty
RDF triples that have resource as object, are available as “inverse” attributes, they follow “is_prefix_predicate_of” convention:
>>> # Print all persons that know john
>>> print john.is_foaf_knows_of
[<surf.session.FoafPerson object at ...>]
Alternatively, dictionary-style attribute access can be used. It is useful in cases where “prefix_predicate” naming convention would yield attribute names that are not valid in Python, like “vcard_postal-code”. It can also be used for easy iterating over a list of attributes:
>>> for attr in ["name", "surname"]: print john["foaf_%s" % attr].first
John
Smith
>>> # URIRefs are also accepted as dictionary keys:
>>> for attr in ["name", "surname"]: print john[surf.ns.FOAF[attr]].first
John
Smith
Attributes can be used as starting points for more involved querying:
>>> # Get first item from ordered list of all friends named "Jane":
>>> john.foaf_knows.get_by(foaf_name = "Jane").order().first()
<surf.session.FoafPerson object at ...>
Modifiers accepted by attributes are described in surf.resource.result_proxy module.
Saving a resource:
resource.save()
Deleting a resource:
resource.remove()
SuRF will allow instantiate resource with any URI and type, regardless of whether such resource is actually present in triple store. To tell if instantiated resource is present in triple store use surf.resource.Resource.is_present() method:
>>> resource = session.get_resource("http://nonexistant-uri", surf.ns.OWL.Thing)
>>> resource.is_present()
False
SuRF Resource objects are all instances of surf.resource.Resource. It is possible to specify additional classes that resources of particular RDF type should subclass. This lets applications add custom logic to resource classes based on their type. The mapping is defined at session level by populating mapping dictionary in session object:
class MyPerson(object):
""" Some custom logic for foaf:Person resources. """
def get_friends_count(self):
return len(self.foaf_knows)
session.mapping[surf.ns.FOAF.Person] = MyPerson
# Now let's test the mapping
john = session.get_resource("http://example/john", surf.ns.FOAF.Person)
# Is `john` an instance of surf.Resource?
print isinstance(john, surf.Resource)
# outputs: True
# Is `john` an instance of MyPerson?
print isinstance(john, MyPerson)
# outputs: True
# Try the custom `get_friends_count` method:
print john.get_friends_count()
# outputs: 0