The rdfrest package

The uniform interface

The cores module

I define the uniform interface of RDF-REST resources ICore.

Optimisation arguments. Several of the methods defined in ICore have so called optimisation arguments. The caller can provide optimisation arguments if they think they can help the implementation, by sparing it the work of either checking data that is known to be correct, or re-computing data that the caller already has. This puts a high responsibility on the caller, who should only set those arguments if they know for certain what they are doing. This is why those arguments have a default value and are semi-private (their name begins with '_'): typically, only subclasses of ICore should use them, and not in all circumstances.

On the other hand, implementations are free to ignore those arguments in situations when they do not trust the caller (e.g. if it acts on behalf of another program).

It follows that, when deriving mix-in classes atop the interfaces defined below, implementors are faced with a delicate choice:

  • either let the implementation do all the checking and computation, which might be sub-optimal;
  • or do the checking and computation itself, which breaks the separation of concerns (TODO DOC link), and will duplicate work if the implementation decides not to trust the client (typically if the implementation is remote).

As a rule of thumb, mix-in implementors should therefore only use optimisation arguments if they have the information at hand, or if they can quickly compute it with information at hand. If they have to rely on the implementation (i.e. call methods from the uniform interface), then they should rather let the implementation do all the work and not use optimisation arguments.

class rdfrest.cores.ICore[source]

Abstract interface of an RDF-REST resource.

uri

An attribute/property holding the URI of this resource.

factory(uri, rdf_types=None, _no_spawn=False)[source]

I return an instance for the resource identified by uri.

If rdf_types is provided, the returned instance will inherit all the registered mix-in classes corresponding to those types.

Parameters:
  • uri (basestring) – the URI of the resource to instanciate
  • rdf_types (list of rdflib.term.URIRef) – if provided, a list of expected RDF types of the resource
Return type:

ICore

Note that this method is only intended to access resources relying on the same implementation as self (i.e. “neighbour” resources). If this is not the case, it may return None even the resource identified by uri exists but is handled by a different implementation. For the latter case, factory.factory() should be used instead.

Optimisation arguments:

Parameters:_no_spawn (bool) – if True, only pre-existing python objects will be returned (may not be honnored by all implementations)

When using this function, it is a good practice to indicate the expected return type, either informally (with a comment) or formally, with a statement of the form:

assert isinstance(returned_object, expected_mixin_class)

Note however that most of the time, one can only know which registered wrapper to expect, not the precise class.

Note

The interface defines this method as an instance method, so that additional method can rely on it to “navigate” from a resource to another, without prior knowledge of the destination resource. It is nonetheless a good idea, whenever possible, to make it a class method, so that the first instance can also be created that way.

get_state(parameters=None)[source]

I return the state of this resource as an RDF graph.

The returned graph will provide a dynamic view of the resource’s state: as much as possible, it will stay up-to-date when the resource changes. It may however get temporarily stale due to cache expiration policy; to prevent that, one can use force_state_refresh().

Parameters:parameters (dict-like) – parameters to alter the meaning of this operation
Return type:rdflib.Graph

IMPORTANT: the graph returned by get_state() is not be used to alter the state of the resource (see edit() for that); the behaviour of the resource if this graph is modified is unspecified.

force_state_refresh(parameters=None)[source]

I force a fresh of the graph returned by get_state().

This method should only be rarely needed, as the graph returned by get_state() usually updates itself.

Parameters:parameters (dict-like) – parameters to alter the meaning of this operation
edit(parameters=None, clear=False, _trust=False)[source]

I return a context for modifying the state of this resource.

Entering this context returns a modifiable graph, containing the state of the resource (just has get_state()). That graph can be modified and the modification will be applied to the resource when exiting the context:

with res.edit() as graph:
    graph.remove(s1, p1, o1)
    graph.add(s2, p2, o2)
# the modifications apply here to res

Note that, while inside the edit context, all methods of the resource (including edit() itself) should not be called, as the internal state of the resource is not in sync with the content of the editable graph (see exception below).

Parameters:
  • parameters (dict-like) – parameters to alter the meaning of this operation
  • clear (bool) – whether the returned graph should be empty rather than initialized with the current state of this resource

The clear parameter above is mostly used when the new state must be parsed from external data rather than modified programatically.

Optimisation arguments:

Parameters:_trust (bool) – if True, the modification will be immediately applied to this resource’s state, without any checking.

It follows that inside a so-called trusted edit context, methods of the resource can still safely be called, including edit() itself. Edit context can therefore be embeded, as long as only the inner-most context is not trusted.

NB: it is an error to set both clear and _trust to True.

post_graph(graph, parameters=None, _trust=False, _created=None, _rdf_type=None)[source]

I post an RDF graph to this resource.

I return the URI of the created resource if any, else None.

Parameters:
  • parameters (dict-like) – parameters to alter the meaning of this operation
  • graph (rdflib.Graph) – the RDF graph to post to this resource
Returns:

the list of created URIs, possibly empty

Optimisation arguments:

Parameters:
  • _trust (bool) – if True, the provided graph is acceptable and requires no modification nor checking.
  • _created (rdflib.term.Node or list of them) – the node(s) from graph that represent the resource(s) to be created
  • _rdf_type (rdflib.term.URIRef or list of them) – the RDF types of the node(s) provided in _created (must have the same size)
delete(parameters=None, _trust=False)[source]

I delete this resource.

Parameters:
  • parameters
  • parameters – a dict-like object containing parameters to alter the meaning of this operation

Optimisation arguments:

Parameters:_trust (bool) – if True, the resource can safely be deleted without any checking.

The factory module

I provide a general core factory.

While ICore.factory aims at producing a resource of the same kind as the target, it may be necessary, in some cases, to navigate a link to a resource of another kind:

  • from a local resource to a remote one
  • from a remote resource to a local one
  • from a local resource to a local resource handled by another service
  • from a remote resource to a remote one using a different protocol

For this, this module provides its own factory() function.

rdfrest.cores.factory.factory(uri, rdf_types=None, _no_spawn=False)[source]

I return an instance for the resource identified by uri.

This module searches all registered implementations for an appropriate one. If none is found (or if the implementation does not recognize the URI), None will be returned.

If rdf_types is provided, the returned instance will inherit all the registered mix-in classes corresponding to those types.

Parameters:
  • uri (basestring) – the URI of the resource to instanciate
  • rdf_types (list of rdflib.term.URIRef) – if provided, a list of expected RDF types of the resource
  • _no_spawn (bool) – if True, only pre-existing python objects will be returned (may not be honnored by all implementations)
Return type:

interface.ICore

When using this function, it is a good practice to indicate the expected return type, either informally (with a comment) or formally, with a statement of the form:

assert isinstance(returned_object, expected_class)

Note that the expected class will usually be an abstract class (a registered mix-in class) rather than a specific implementation.

But this function needs to know all the implementations of interface.ICore and all implemented services. This is what register_implementation() and register_service() are about, respectively.

rdfrest.cores.factory.register_implementation(uri_prefix)[source]

Registers a subclass of interface.ICore.

This is to be used as a decorator generator, as in:

@register_implementation("xtp://")
class XtpResource(rdfrest.interface.ICore):
    '''Implementation of REST resource over the XTP protocol.'''
    #...
Parameters:uri_prefix (str) – the URI prefix that this implementation can handle
Returns:the class decorator

The decorated class must implement factory as a class method.b

rdfrest.cores.factory.register_service(service)[source]

Register a local.Service.

NB: this need normally not be called directly, as local.Serice.__init__() already does it.

rdfrest.cores.factory.unregister_service(service)[source]

Unregister a local.Service.

NB: this beed normally not be called directlt, as local.Serice.__del__() already does it.

Note that this module automatically registers all the implementations shipped with rdfrest; furthermore, local.Service automatically registers all its instances. However, you should check before you call factory() that:

  • all the external implementations have been registered (this is usually done by simply importing them, as register_implementation() is meant to be used as a class decorator);
  • all the services you rely on have been instanciated.

Remote implementations

The http_client module

I implement interface.ICore over HTTP.

rdfrest.cores.http_client.set_http_option(key, value)[source]

I set an option for future HTTP connexions.

Those options will be passed to httplib2.Http for all future HttpClientCores. Note that resources can be cached, so it is only safe to call this function before any resource is created.

rdfrest.cores.http_client.add_http_credentials(username, password)[source]

I add credentials to future HTTP connexions.

Those credentials will be added to the underlying httplib2.Http of all future HttpClientCores. Note that resources can be cached, so it is only safe to call this function before any resource is created.

rdfrest.cores.http_client.add_http_certificate(key, cert, domain)[source]

I add a certificate to future HTTP connexions.

Those credentials will be added to the underlying httplib2.Http of all future HttpClientCores. Note that resources can be cached, so it is only safe to call this function before any resource is created.

class rdfrest.cores.http_client.HttpClientCore(uri, graph=None)[source]

A RESTful resource over HTTP

Parameters:uri – this resource’s URI
uri

I implement interface.ICore.uri.

I hold this resource’s URI as defined at __init__ time.

classmethod factory(self_or_cls, uri, rdf_types=None, _no_spawn=False)[source]

I implement interface.ICore.factory().

Note that I implement it as a class method, so a first resource can be created from its URI without prior knowledge with:

res = HttpClientCore.factory(uri)

Note also that _rdf_type is ignored.

Return type:HttpClientCore or HostedCore

NB: if uri contains a fragment-id, the returned resource will be a HostedCore hosted by a HttpClientCore .

get_state(parameters=None)[source]

I implement interface.ICore.get_state().

force_state_refresh(parameters=None)[source]

I implement interface.ICore.force_state_refresh.

edit(parameters=None, clear=False, _trust=False)[source]

I implement interface.ICore.edit().

post_graph(graph, parameters=None, _trust=False, _created=None, _rdf_type=None)[source]

I implement interface.ICore.post_graph().

delete(parameters=None, _trust=False)[source]

I implement interface.ICore.delete().

get_subresource(parameters)[source]

I return version of this resource with additional parameters.

I raise InvalidParametersError if that resource can not be constructed.

rdfrest.cores.http_client.rm_rf(dirname)[source]

Recursively remove directory dirname.

The hosted module

I implement interface.ICore as a resource “hosted” by another one.

class rdfrest.cores.hosted.HostedCore(host_resource, uri, forward_params=True)[source]

A RESTful resource whose description is embeded in another resource.

This is typically used for resources with a fragment-id in their URI, but also for non-informational resource using 303-redirect.

Parameters:
  • host_resource (interface.ICore) – the host resource
  • uri (basestring) – this resource’s URI (may be relative to host’s)
  • forward_params (bool) – whether parameters should be forwarded to host (see below)

Argument forward_params defaults to True (which makes sense for fragment-id hosted resource) but may be disabled (which makes sense for 303-redirect hosted resource).

uri

I implement interface.ICore.uri.

I hold this resource’s URI as defined at __init__ time.

factory(uri, rdf_types=None, _no_spawn=False)[source]

I implement interface.ICore.factory().

I simply rely on my host’s factory.

get_state(parameters=None)[source]

I implement interface.ICore.get_state().

I simply return my host’s state.

force_state_refresh(parameters=None)[source]

I implement interface.ICore.force_state_refresh.

I simply force a state refresh on my host.

edit(parameters=None, clear=False, _trust=False)[source]

I implement interface.ICore.edit().

I simply return my host’s edit context.

post_graph(graph, parameters=None, _trust=False, _created=None, _rdf_type=None)[source]

I implement interface.ICore.post_graph().

No data can be posted to a hosted resource; it should be posted to the host resource instead.

delete(parameters=None, _trust=False)[source]

I implement interface.ICore.delete().

A hosted resource can not be deleted. The host resource should be altered instead.

classmethod handle_fragments(factory)[source]

I decorate a resource factory to have it handle URIs with frag-id.

If the URI passed to the factory contains a fragment ID, I will try to use the decorated factory to make the host (fragment-less) resource, and return the corresponding hosted resource.

Else, I will pass the URI through to the decorated factory.

Local implementation

The local module

I provide a local implementation of interface.ICore.

“Local” means either standalone or server-side. The difference with a “remote” implementation (e.g. client-side) is that the local implementation must implement the concerns of the server.

  • A Service is the central component managing a set of local resources with a common URI prefix (the service’s root). When initialized, a service is passed a list of the ICore implementations it will manage.
  • More precisely, the classes passed to a Service must implement ILocalCore, a sub-interface of ICore augmenting it with attributes and hooks methods aimed at managing the concerns of the server (integrity checking, update propagations...).
  • This module provides default implementations of ILocalCore: LocalCore (supporting only “read” operations) and EditableCore (supporting edit() and delete()).
  • Subclasses of ILocalCore can also benefit from a number of mix-in classes provided in the mixins module.
class rdfrest.cores.local.Service(classes, service_config=None, init_with=None)[source]

I manage a set of related ILocalCore‘s.

All the resources in a service are stored in the same rdflib.store.Store.

Parameters:
  • classes – a list of classes to be used by this service (see below)
  • service_config – kTBS configuration
  • init_with – a callable to initialize the store if necessary (i.e. at least populate the root resource); it will be passed this service as its sole argument.

root_uri (str), the URI of the root resource of this service store (rdflib.store.Store), the RDF store containing the data of this service init_with, a callable to initialize the store if necessary (i.e. at least populate the root resource); it will be passed this service as its sole argument.

The classes passed to this service should all be subclasses of ILocalCore, and all have an attribute RDF_MAIN_TYPE indicating the RDF type they implement.

get(self_or_cls, uri, rdf_types=None, _no_spawn=False)[source]

Get a resource from this service.

Parameters:
  • uri (URIRef) – the URI of the resource
  • rdf_types (list of rdflib.term.URIRef) – if provided, a list of expected RDF types of the resource
  • _no_spawn (bool) – if True, only pre-existing python objects will be returned
Returns:

the resource, or None

Return type:

ILocalCore or HostedCore

TODO NOW: if no resource is found, try to get it from parent resource

NB: if uri contains a fragment-id, the returned resource will be a HostedCore hosted by a resource from this service.

When using this function, it is a good practice to indicate the expected return type, either informally (with a comment) or formally, with a statement of the form:

assert isinstance(returned_object, expected_class)
get_metadata_graph(uri)[source]

Return the metadata graph for the resource identified by uri

Parameters:uri – the URI of the resou
Returns:the metadata graph
Return type:rdflib.graph.Graph
class rdfrest.cores.local.ILocalCore[source]

A RESTful resource implemented by a local Service.

I merely define the interface that service resources must implement, in addition to implementing interface.ICore.

The attributes and methods it defines must, of course, be only used in implementation-related code; API-related code must only rely on the uniform interface of interface.ICore.

service

The Service this resource depends on.

check_parameters(to_check, parameters, method)[source]

I checks whether parameters are acceptable. I may also alter parameters to normalize or format its values.

This hook method is called whenever a method from interface.ICore is invoked, and raises an InvalidParametersError if the given parameters are not acceptable for the given method.

When a subclass does not recognizes some of the parameters, it must call the superclass’s check_parameters, including only the names of the unrecognized parameters in to_check. On the other hand, if it exhausts the parameter list, the subclass is not required to call the superclass’s check_parameters.

Parameters:
  • to_check (iterable of keys existing in parameters, or None) – the names if the parameters to check
  • parameters (dict or None) – the dict containing the parameters
  • method (unicode) – the name of the calling python method
Raise:

exceptions.InvalidParametersError

classmethod complete_new_graph(service, uri, parameters, new_graph, resource=None)[source]

I alter a graph for representating a resource of this class.

This hook method is to be called when a resource of this class is either created and updated, before check_new_graph() is called.

Parameters:
  • service (Service) – the service to which new_graph has been posted
  • uri (rdflib.URIRef) – the URI of the resource described by new_graph
  • parameters (dict or None) – the query string parameters passed to edit if any
  • new_graph (rdflib.Graph) – graph to check

The following parameter will always be set when complete_new_graph is used to update and existing resource; for creating a new resource, it will always be None.

Parameters:resource – the resource to be updated

This class method can be overridden by subclasses tat have need to automatically generate or update parts of their representation.

classmethod check_new_graph(service, uri, parameters, new_graph, resource=None, added=None, removed=None)[source]

I check that a graph is a valid representation for a resource.

This hook method is to be called when a resource of this class is either created and updated, to verify if new_graph is acceptable.

Parameters:
  • service (Service) – the service to which new_graph has been posted
  • uri (rdflib.URIRef) – the URI of the resource described by new_graph
  • parameters (dict or None) – the query string parameters passed to edit if any
  • new_graph (rdflib.Graph) – graph to check

The following parameter will always be set when check_new_graph is used to update and existing resource; for creating a new resource, it will always be None.

Parameters:resource – the resource to be updated

The following parameters only make sense when updating an existing resource. They are not automatically set by edit(), as they may not be used. However, any implementation may set them by using compute_added_and_removed() and should therefore pass them along the super calls.

Parameters:
  • added – if not None, an RDF graph containg triples to be added
  • removed – if not None, an RDF graph containg triples to be removed

The return value should be an empty Diagnosis if the new graph is acceptable, else it should contain a description of the problem(s).

Return type:Diagnosis
classmethod mint_uri(target, new_graph, created, basename=None, suffix='')[source]

I mint a fresh URI for a resource of that class.

This method is called by rdfrest.cores.mixins.GraphPostableMixin; calling it directly is usually not required.

Parameters:
  • target (ILocalCore) – the resource to which new_graph has been posted
  • new_graph (rdflib.Graph) – a description of the resource for which to mint a URI
  • created (rdflib.Node) – the non-URIRef node representing the resource in $`new_graph`
  • basename (str) – a base on which the last part of the URI will be generated
  • suffix (str) – a string that will be added at the end of the URI
Return type:

rdflib.URIRef

classmethod create(service, uri, new_graph)[source]

I create a resource of this class in service.

This method is responsible of actually storing the resource in the service.

Parameters:
  • service (Service) – the service in which to create the resource
  • uri (rdflib.URIRef) – the URI of the resource to create
  • new_graph (rdflib.Graph) – RDF data describing the resource to create; it is assumed to have passed check_new_graph()
prepare_edit(parameters)[source]

I perform some pre-processing before editing this resource.

I return an object that will be passed to ack_edit() as parameter prepared. This object can be used to cache some information from the original state that will be required by ack_edit().

This hook method is to be called on entering the edit() context.

Parameters:parameters (dict or None) – the query string parameters passed to edit if any
Return type:a mutable object
ack_edit(parameters, prepared)[source]

I perform some post-processing after editing this resource.

This hook method is to be called when exiting the edit() context; calling it directly may corrupt the service.

Parameters:
  • parameters (dict or None) – the query string parameters passed to edit if any
  • prepared – the object returned by prepare_edit()

Note to implementors: ack_edit() may alter the state of the resource using the edit() context, but is required to pass True to its _trust parameter, leaving you the responsibility of maintaining the integrity of the resource’s state).

check_deletable(parameters)[source]

I check that this resource can safely be deleted.

This hook method is to be called on entering the delete() method.

Parameters:parameters (dict or None) – the querystring parameters passed to delete if any
Return type:util.Diagnosis

This class method can be overridden by subclasses that have constraints on whether their instances can be deleted.

ack_delete(parameters)[source]

I perform some post processing after deleting this resource.

This hook method is to be called on exiting the delete() method; calling it directly may corrupt the service.

Parameters:parameters (dict or None) – the querystring parameters passed to delete if any

Note to implementors: this method is actually called just before the public and metadata graphs of this resource are emptied, so all the information is still available to this method. Care should nonetheless be taken not to call methods that might alter other resources as if this one was to continue existing.

class rdfrest.cores.local.LocalCore(service, uri)[source]

I provide a default implementation of ILocalCore.

The state of a local core is stored in the service’s store as an individual graph, identified by the resource’s URI.

metadata

A graph containing some metadat about this resource, for internal use (not exposed by get_state()).

__init__(service, uri, graph_uri=None)[source]
Parameters:
  • service (Service) – the service this resource depends on
  • uri (rdflib.URIRef) – the URI of this resource
factory(uri, rdf_types=None, _no_spawn=False)[source]

I implement interface.ICore.factory().

get_state(parameters=None)[source]

I implement interface.ICore.get_state().

I will first invoke check_parameters().

The returned graph may have an attribute redirected_to, which is used to inform http_server that it should perform a redirection.

force_state_refresh(parameters=None)[source]

I implement interface.ICore.force_state_refresh().

I will first invoke check_parameters().

edit(parameters=None, clear=False, _trust=False)[source]

I implement interface.ICore.edit().

By default, I do not support it. See EditableCore to add support.

post_graph(graph, parameters=None, _trust=False, _created=None, _rdf_type=None)[source]

I implement interface.ICore.post_graph().

By default, I do not support it. See GraphPostableMixin to add support.

delete(parameters=None, _trust=False)[source]

I implement interface.ICore.delete().

By default, I do not support it. See EditableCore to add support.

check_parameters(to_check, parameters, method)[source]

I implement ILocalCore.check_parameters().

I accepts no parameter.

classmethod complete_new_graph(service, uri, parameters, new_graph, resource=None)[source]

I implement ILocalCore.complete_new_graph().

I leave the graph unchanged.

classmethod check_new_graph(service, uri, parameters, new_graph, resource=None, added=None, removed=None)[source]

I implement ILocalCore.check_new_graph().

I accept any graph.

classmethod mint_uri(target, new_graph, created, basename=None, suffix='')[source]

I implement ILocalCore.mint_uri().

I generate a child URI of target‘s uri, with a name derived from the basename (defaulting to the class name converted to lower case), ensuring that the generated URI is not in use in target.graph.

classmethod create(service, uri, new_graph)[source]

I implement ILocalCore.create().

I store new_graph as is in this resource’s graph, and adds a hint to this class in the metadata graph.

class rdfrest.cores.local.EditableCore(service, uri)[source]

I implement edit and delete from interface.ICore.

In addition to the helper and hook methods defined by ILocalCore, this class defines a few others that are specific to edit() and delete().

edit(parameters=None, clear=False, _trust=False)[source]

I implement interface.ICore.edit().

On entering the context, I will invoke check_parameters(), then I will invoke prepare_edit().

I will also raise a ValueError if an inner context uses not-None parameters that are different from the parameters of the outer context.

On exiting an untrusted edit context, I will invoke complete_new_graph() and then check_new_graph(), and raise an InvalidDataError if the later returns an error. Finally, ack_edit() will be invoked.

On existing a trusted edit context, only ack_edit() will be invoked, as the modifications are supposed to be acceptable.

Several trusted contexts can be embeded, provided that the inner context use either the exact same parameters as the outermost context or no parameter at all (None). In that case, prepare_edit() and ack_edit() will only be called in the outermost context.

Note also that ack_edit() can itself open a trusted edit context if it needs to modify the resource’s state.

Note

On exiting a trusted edit context, check_new_graph() is nonetheless asserted, so implementors may notice that, if they mistakenly make an invalid modification in a trusted edit context, this will be detected and raise an AssertionError.

This should however not be relied upon, for the following reasons:

  • assertions only occur in __debug__ mode, not in optimize mode;
  • not all tests will be performed by the assertions (see more detail in the commented source).
delete(parameters=None, _trust=False)[source]

I implement interface.ICore.delete().

I will first invoke check_parameters(). I will then invoke check_deletable() to check whether this resource can be deleted. If so, I will empty its graph and its metadata graph, then call ack_delete().

After calling this method, the resource object is unsusable and should be immediatetly discarded.

prepare_edit(parameters)[source]

I implement ILocalCore.prepare_edit().

The default implementation returns an empty object.

ack_edit(parameters, prepared)[source]

I implement ILocalCore.ack_edit().

The default implementation does nothing.

check_deletable(parameters)[source]

I implement ILocalCore.check_deletable().

The default always accepts.

ack_delete(parameters)[source]

I implement ILocalCore.ack_delete().

The default implementation does nothing.

rdfrest.cores.local.compute_added_and_removed(new_graph, old_graph, added=None, removed=None)[source]

I compute the graphs of added triples and of removed triples.

For overridden versions of check_new_graph that require added and removed to be set, I should be called as:

added, removed = self._compute_added_and_removed(
    new_graph, old_graph, added, removed)

If added and removed are not None, this method will simply return them, preventing the overhead of computing them again.

However, it is important to call this function before the call to super(...).check_new_graph, because the result is not transmitted to the calling function. So to ensure that the computation happens only once, it must be performed at the highest level that needs it.

The mixins module

I provide additional useful mixin classes to be used with local.ILocalCore.

class rdfrest.cores.mixins.BookkeepingMixin[source]

I add bookkeeping metadata to the mixed-in class.

Bookkeeping metadata consist of:

  • a weak etag (as defined in section 13.3 of RFC 2616)
  • a last-modified data

Note

We are using weak etags, because we can not guarantee that serializers always give the exact same output for a given graph.

iter_etags(parameters=None)[source]

I return an iterable of the etags of this resource.

This implementation only yields one etag, regardless of parameters, but subclasses could override this to yield more, and return different etags depending on parameters.

last_modified

I return the time when this resource was last modified.

Returns:number of seconds since EPOCH, as returned by time.time()
classmethod create(service, uri, new_graph)[source]

I override local.ILocalCore.create() to generate bookkeeping metadata.

ack_edit(parameters, prepared)[source]

I override local.ILocalCore.ack_edit() to update bookkeeping metadata.

class rdfrest.cores.mixins.FolderishMixin[source]

I implement interface.ICore.post_graph().

This mixin enforces that the resources of this class have a ‘/’-terminated URI.

classmethod check_new_graph(service, uri, parameters, new_graph, resource=None, added=None, removed=None)[source]

I override local.ILocalCore.check_new_graph() to force the URI to end with a ‘/’.

classmethod mint_uri(target, new_graph, created, basename=None, suffix='')[source]

I override local.ILocalCore.mint_uri() to force the URI to end with a ‘/’.

class rdfrest.cores.mixins.GraphPostableMixin[source]

I implement interface.ICore.post_graph().

This is a typical implementation where the posted graph represents a single resource that will be created as a “child” of this resource. This is why this mix-in class should usually be used with FolderishMixin.

In addition to the helper and hook methods defined by local.ILocalCore, this mixin class defines a few others that are specific to post_graph().

post_graph(graph, parameters=None, _trust=False, _created=None, _rdf_type=None)[source]

I implement interface.ICore.post_graph().

I will first invoke check_parameters().

I will then invoke find_created() to locate the node to be created in the posted graph, and check_posted_graph() to check whether the posted graph is acceptable. Finally, get_created_class() will be used to identify the python class of the resource to be created.

From that class, the following methods will be used (in this order): mint_uri() to generate the URI of the resource to be created (only if it was a BNode in the posted graph); complete_new_graph(), then check_new_graph(), and finally create().

Optimisation. If _created is provided, find_created() will not be used. If _trust is provided, none of check_posted_graph(), complete_new_graph() nor check_new_graph() will be used (in fact, check_posted_graph() and check_new_graph() may be asserted so that errors are detected earlier. But as asserts are only executed in __debug__ mode, this should obviously not be relied upon).

find_created(new_graph)[source]

Find the node representing the resource to create in new_graph.

Parameters:new_graph (rflib.Graph) – the posted RDF graph
Returns:the node representing the resource to create, or None if it can not be found.
Return type:rdflib.Node

The default behaviour is to run _find_created_default() with a query returning all nodes linked to uri. Subclasses may also find it useful to rely on _find_created_default(), passing it a more specific query.

check_new(created)[source]

Proxy to check_new() that can be overrided by children classes.

check_posted_graph(parameters, created, new_graph)[source]

Check whether new_graph is acceptable to post on this resource.

Note that the purpose of this method is different from ILocalCore.check_new_graph(): while the latter implements the concerns of the resource to be created, this method implements the concerns of the target of the post.

Parameters:
  • parameters (dict or None) – the query string parameters passed to post_data
  • created (rdflib.Node) – the node representing the resource to create
  • new_graph (rflib.Graph) – the posted RDF graph
Return type:

a util.Diagnosis

This implementation only checks that the ‘created’ node is not already in use in this resource’s graph.

get_created_class(rdf_type)[source]

Get the python class to use, given an RDF type.

The default beheviour is to use self.service.class_map but some classes may override it.

Return type:a subclass of ILocalCore
ack_post(parameters, created, new_graph)[source]

I perform some post processing after a graph has been posted.

This hook method is called by post_graph(); calling it directly may corrupt the service.

Parameters:
  • parameters (dict or None) – the query string parameters passed to post_data
  • created (rdflib.Node) – the node representing the create resource
  • new_graph (rflib.Graph) – the posted RDF graph

The default implementation does nothing.

class rdfrest.cores.mixins.WithReservedNamespacesMixin[source]

I add reserved namespaces to the mixed-in class.

A reserved namespace is a set of URIs (defined by a common prefix) which can not be freely used in the description of the resource, as they have a specific meaning for the application.

Reserved namespaces are listed in the RDF_RESERVED_NS class variable (in addition to those inherited from superclasses).

The reserved namespace applies to URIs used as predicates and types. The default rule is that they can not be added at creation time (in a graph passed to post_graph()) nor at edit() time. They can only be inserted and modified by the service itself (i.e. in create() or in a trusted edit() contexts).

It is however possible to provide exceptions for a class, i.e. URIs inside a reserved namespace which can freely set: at creation time only, or at edit time (including creation); as incoming property, outgoing property or type. All those exceptions are listed in the corresponding class attributes from the list below (in addition to those inherited from superclasses).

  • RDF_CREATABLE_IN
  • RDF_CREATABLE_OUT
  • RDF_CREATABLE_TYPES
  • RDF_EDITABLE_IN
  • RDF_EDITABLE_OUT
  • RDF_EDITABLE_TYPES

Note that the RDF_MAIN_TYPE is always implictly added to RDF_CREATABLE_TYPES so it is not necessary to specify it there.

NB: the values of the class attributes are not supposed to change over time; if they do, the change may not be effective.

classmethod check_new_graph(service, uri, parameters, new_graph, resource=None, added=None, removed=None)[source]

I overrides local.ILocalCore.check_new_graph() to check the reserved namespace constraints.

class rdfrest.cores.mixins.WithCardinalityMixin[source]

I add cardinality constrains on some properties.

I provide means to express cardinality constraints on some predicate, used as incoming and/or outgoing properties, and override check_new_graph to enforce those constraints.

Cardinality constraints are listed in the following class variables, expressed as tuples of the form (predicate_uri, min_cardinality, max_cardinality), respectively for incoming and outgoing properties. None can be used for min_cardinality or max_cardinality to mean “no constraint”.

  • RDF_CARDINALITY_IN
  • RDF_CARDINALITY_OUT

NB: the values of the class variables are not supposed to change over time; if they do, the change may not be effective.

classmethod check_new_graph(service, uri, parameters, new_graph, resource=None, added=None, removed=None)[source]

I overrides local.ILocalCore.check_new_graph() to check the cardinality constraints.

class rdfrest.cores.mixins.WithTypedPropertiesMixin[source]

I add constrains on the datatype of some property values.

I provide means to force some properties to have only URIs or literals as their values, and to constrain the datatype of the said literal.

Type constraints are listed in the RDF_TYPED_PROP class variable, expressed as tuples of the form (predicate_uri, node_type[, value_type]) where node_type is either the string “uri” or the string “literal”. If node_type is “uri” and value_type is provided, then it further requires the property value to have node_type as its rdf:type. If node_type is “literal” and value_type is provided, then it further requires the property value to have node_type as its datatype.

Note that a blank node is acceptable if the node type is “uri”, and that plain and language-tagged literals are acceptable if the datatype is xsd:string.

Note also that this implementation does no inference on the rdf types not on the datatype hierarchy; so the graph must explicitly contain the required value type (if any), else it will be rejected.

classmethod check_new_graph(service, uri, parameters, new_graph, resource=None, added=None, removed=None)[source]

I overrides local.ILocalCore.check_new_graph() to check the cardinality constraints.

The http_server module

I implement a WSGI-based HTTP server wrapping a given cores.local.Service.

class rdfrest.http_server.MyRequest(environ, charset=None, unicode_errors=None, decode_param_names=None, **kw)[source]

I override webob.Request by allowing weak etags.

if_match

Gets and sets the If-Match header (HTTP spec section 14.24). Converts it as a Etag.

class rdfrest.http_server.MyResponse(body=None, status=None, headerlist=None, app_iter=None, content_type=None, conditional_response=None, **kw)[source]

I override webob.Response’s default behaviour.

class rdfrest.http_server.HttpFrontend(service, service_config)[source]

The role of the WSGI front-end is to relay requests to and response from the service through the HTTP protocol.

For parsing and serializing payloads to and from RDF graphs, HttpFrontend relies on the functions registered in cores.local.parsers and cores.local.serializers.

In the future, WsgiFrontent may also include on-the-fly translation of contents, for changing internal URIs into URIs served by the HttpFrontend.

Warning

RDF-REST is meant to differenciate an empty query-string from no query-string at all. However, WSGI does not allow such a distinction. This implementation therefore assumes that an empty query-string is no query-string at all.

http_delete(request, resource)[source]

Process a DELETE request on the given resource.

http_get(request, resource)[source]

Process a GET request on the given resource.

http_head(request, resource)[source]

Process a HEAD request on the given resource.

http_options(request, resource)[source]

Process an OPTIONS request on the given resource.

http_post(request, resource)[source]

Process a POST request on the given resource.

http_put(request, resource)[source]

Process a PUT request on the given resource.

Note

If resource has an iter_etags properties, then it is required that request include an If-Match header field. Note that those etags are weak etags (see BookkeepingMixin), which are not allowed in If-Match according to RFC 2616. However, this limitation will probably be dropped in future versions of HTTP, so do not follow it.

issue_error(status, request, resource, message=None, **kw)[source]

Issues an HTTP error.

Parameters:
  • status (int) – the HTTP status
  • request (MyRequest) – the request being processed
  • resource (rdfrest.cores.local.ILocalCore) – the resource being addressed (can be None)
  • message (str) – the payload of the error response
  • kw – header fields to add to the response

Can be overridden by subclasses to provide custom error messages.

rdfrest.http_server.taint_etag(etag, ctype)[source]

I taint etag with the given content-type.

This is required because caches may be smart with different entities of the same resources, as described in RFC 2616, sec 13.6.

rdfrest.http_server.cache_half_last_modified(resource)[source]

I use last-modified to provide cache-control directive.

If resource has a last_modified property (assumed to return a number of seconds since EPOCH), I allow to cache resource for half the time since it was last modified.

Else, I return None.

rdfrest.http_server.register_middleware(level, middleware, quiet=False)[source]

Register a middleware for HTTP requests.

In addition to standard WSGI entries, the environ passed to middlewares will include:

  • rdfrest.resource: the requested resource; may be None
  • rdfrest.requested.uri: the URI (as an rdflib.URIRef) requested by the client, without its extension (see below)
  • rdfrest.requested.extension: the requested extension; may be ""
Parameters:
  • level – a level governing the order of execution of pre-processors; predefined levels are AUTHENTICATION, AUTHORIZATION
  • middleware – a function accepting a WSGI application, and producing a WSGI application wrapping the former
rdfrest.http_server.unregister_middleware(middleware, quiet=False)[source]

Unregister a middleware for HTTP requests.

class rdfrest.http_server.ErrorHandlerMiddleware(app)[source]

I intercept a wide range of exceptions, and convert them to HTTP errors.

exception rdfrest.http_server.UnauthorizedError(message='', challenge=None, **headers)[source]

An error raised when a remote user is not authorized to perform an action.

exception rdfrest.http_server.RedirectException(location, code=303, **headers)[source]

An exception raised to redirect a given query to another URL.

rdfrest.http_server.pre_process_request(service, request, resource)[source]

Applies all registered pre-processors to request.

rdfrest.http_server.register_pre_processor(level, preproc, quiet=False)[source]

Register a pre-processor for HTTP requests.

Parameters:
  • level – a level governing the order of execution of pre-processors; predefined levels are AUTHENTICATION, AUTHORIZATION
  • preproc – a function accepting 3 parameters: a Service, a Webob request and an RdfRest resource
rdfrest.http_server.unregister_pre_processor(preproc, quiet=False)[source]

Unregister a pre-processor for HTTP requests.

Parsing and serialising representations

The parsers module

I provide functionalities to parse RDF-REST resource.

I act as a registry of parsers. Parsers can be iterated by decreasing preference or extension.

I provide a number of default parsers, but additional parsers can be added in the registry.

rdfrest.parsers.register_parser(content_type, extension=None, preference=80)[source]

I return a decorator for registering a parser.

The decorated function must have the same prototype as parse_rdf_xml().

Parameters:
  • content_type – a content-type as a str
  • extension – the file extension associated with this parser
  • preference – an int between 0 (low) and 100 (high)

The decorated function must have the same prototype as parse_rdf_xml(), and should raise ~.exceptions.ParseError when it fails to parse the given content.

rdfrest.parsers.iter_parsers()[source]

Iter over all the parsers available for this rdf_type.

Returns:an iterator of tuples (parser_function, content_type, extension)

Parsers are iterated in decreasing order of preference.

rdfrest.parsers.get_parser_by_content_type(content_type)[source]

I return the best parser associated with content_type, or None.

Returns:a tuple (parser_function, extension) or (None, None)
rdfrest.parsers.get_parser_by_extension(extension)[source]

Return the parser associated with the best preference score.

Returns:a tuple (parser_function, content_type) or (None, None)
rdfrest.parsers.parse_rdf_xml(content, base_uri=None, encoding='utf-8', graph=None)[source]

I parse RDF content from RDF/XML.

Parameters:
  • content – a byte string
  • base_uri – the base URI of content
  • encoding – the character encoding of content
  • graph – if provided, the graph to parse into
Returns:

an RDF Graph

Raise:

rdfrest.exceptions.ParseError

rdfrest.parsers.parse_turtle(content, base_uri=None, encoding='utf-8', graph=None)[source]

I parse RDF content from Turtle.

See parse_rdf_xml for prototype documentation.

rdfrest.parsers.parse_ntriples(content, base_uri=None, encoding='utf-8', graph=None)[source]

I parse RDF content from N-Triples.

See parse_rdf_xml for prototype documentation.

The serializers module

I provide functionalities to serialize RDF-REST resource.

I act as a registry of serializers. Serializers can be iterated by decreasing preference or extension, and dedicated serializers can be registered for a given RDF type.

I provide a number of default serializers, but additional serializers can be added in the registry.

Finally, a numer of default namespace prefixes <bind_prefix>:func` can be set. They will be shared with all registered serializers (but some third-party serializers may not honnor them).

rdfrest.serializers.register_serializer(content_type, extension=None, preference=80, rdf_type=None)[source]

I return a decorator for registering a serializer.

The decorated function must have the same prototype as serialize_rdf_xml().

Parameters:
  • content_type – a content-type as a str
  • extension – the file extension associated with this serializer
  • preference – an int between 0 (low) and 100 (high)
  • rdf_type – if provided, the RDF type to which this serializer applies

The decorated function must have the same prototype as serialize_rdf_xml(), and should raise ~.exceptions.SerializeError when it fails to serialize the given graph.

rdfrest.serializers.iter_serializers(rdf_type=None)[source]

Iter over all the serializers available for this rdf_type.

Returns:an iterator of tuples (serializer_function, contenttype, extension)

Serializers are iterated in decreasing order of preference. Note that, if rdf_type is provided, a serializer associated with this type will always be preferred over a generic serializer (i.e. associated with no type), regardless of the preference score.

rdfrest.serializers.get_serializer_by_content_type(content_type, rdf_type=None)[source]

I return the best serializer associated with content_type, or None.

Returns:a tuple (serializer_function, extension) or (None, None)
rdfrest.serializers.get_serializer_by_extension(extension, rdf_type=None)[source]

Return the serializer associated with the best preference score.

Returns:a tuple (serializer_function, content_type) or (None, None)
rdfrest.serializers.bind_prefix(prefix, namespace_uri)[source]

I associate a namespace with a prefix for all registered serializers.

rdfrest.serializers.get_prefix_bindings()[source]

I return a fresh dict containing all the prefix bindings.

See also:bind_prefix()
rdfrest.serializers.serialize_rdf_xml(graph, resource, bindings=None)[source]

I serialize an RDF graph as RDF/XML.

Parameters:
  • graph – the Graph to serialize
  • resource – the resource described by graph (its URI will used as base URI)
  • binding – a dict containing system-wide prefix bindings (defaults to get_prefix_bindings:func:())
Returns:

an iterable of UTF-8 encoded byte strings

Raise:

exceptions.SerializeError if the serializer can not serialize the given graph.

Important

Serializers that may raise a SerializeError must not be implemented as generators, or the exception will be raised too late (i.e. when the HttpFrontend tries to send the response.

rdfrest.serializers.serialize_turtle(graph, uri, bindings=None)[source]

I serialize an RDF graph as Turtle.

See serialize_rdf_xml for prototype documentation.

rdfrest.serializers.serialize_ntriples(*args, **kw)[source]

I serialize an RDF graph as N-Triples.

See serialize_rdf_xml for prototype documentation.

rdfrest.serializers.serialize_html(*args, **kw)[source]

I return a JS based REST console, that will then load the graph from the default serializer.

Other utility modules

The exceptions module

I provide standard exception for RDF-REST.

exception rdfrest.exceptions.RdfRestException(arg=None)[source]

The common superclass of all RDF-REST exceptions.

Parameters:arg – can be either a message or an exception to embed
exception rdfrest.exceptions.CorruptedStore(arg=None)[source]

An error raised when the RDF store is in an unexpected state.

exception rdfrest.exceptions.CanNotProceedError(arg=None)[source]

An error raised when the state of the RDF-REST service prevents from completing a request.

For example: a resource can not be deleted because other resources depend on it.

exception rdfrest.exceptions.InvalidDataError(arg=None)[source]

An error raised when RDF data is not acceptable.

exception rdfrest.exceptions.InvalidParametersError(arg=None)[source]

An error raised when query-string parameters are not acceptable.

This means that the query-string parameters correspond to no resource. If the parameters are recognized but do not support the intended operation, MethodNotAllowedError should be raised instead.

exception rdfrest.exceptions.InvalidUriError(arg=None)[source]

An error raised when the URI used to create a resource is not acceptable.

exception rdfrest.exceptions.MethodNotAllowedError(message)[source]

An error raised when an RDF-REST method is not supported.

exception rdfrest.exceptions.ParseError(arg=None)[source]

An error during parsing a user-provided content.

exception rdfrest.exceptions.SerializeError(arg=None)[source]

An error during serializing a graph.

Parameters:arg – can be either a message or an exception to embed

The util module

I define useful functions and classes for RDF RESTful services.

rdfrest.util.add_uri_params(uri, parameters)[source]

Add query-string parameters to a given URI.

Parameters:uri (basestring) – the URI to add the paramateres to
Para dict-like parameters:
 the parameters to add to the URI
rdfrest.util.bounded_description(node, graph, fill=None, prune=None)[source]

Extract from graph a bounded description of node.

Parameters:
  • node – the node (uri or blank) to return a description of
  • graph – the graph from which to retrieve the description
  • fill – if provided, fill this graph rather than a fresh one, and return it
  • prune – if provided, a container of bnodes that should not be recursed into
rdfrest.util.cache_result(callabl)[source]

Decorator for caching the result of a callable.

It is assumed that callabl only has a self parameter, and always returns the same value.

rdfrest.util.check_new(graph, node)[source]

Check that node is absent from graph.

rdfrest.util.coerce_to_uri(obj, base=None)[source]

I convert obj to a URIRef.

Parameters:
  • obj – either an rdflib.URIRef, an object with a uri attribute (assumed to be a URIRef) or a string-like URI.
  • base – if provided, a string-like absolute URI used to resolve obj if it is itself a string.
Return type:

rdflib.URIRef

rdfrest.util.coerce_to_node(obj, base=None)[source]

I do the same as coerce_to_uri() above, but in addition:

  • if obj is None, I will return a fresh BNode
  • if obj is a BNode, I will return it
rdfrest.util.extsplit(path_info)[source]

Split a URI path into the extension-less path and the extension.

rdfrest.util.make_fresh_uri(graph, prefix, suffix='')[source]

Creates a URIRef which is not in graph, with given prefix and suffix.

rdfrest.util.parent_uri(uri)[source]

Retun the parent URI of ‘uri’.

rdfrest.util.random_token(length, characters='0123456789abcdefghijklmnopqrstuvwxyz', firstlimit=10)[source]

Create a random opaque string.

Parameters:
  • length – the length of the string to generate
  • characters – the range of characters to use
  • firstlimit – see below

The parameter firstlimit is use to limit the first character of the token to a subrange of characters. The default behaviour is to first the first character of the token to be a digit, which makes it look more “tokenish”.

rdfrest.util.replace_node_dense(graph, old_node, new_node)[source]

Replace a node by another in graph.

IMPORTANT: this method assumes that old_node will be used in most triples, so performs the replacement on all triples.

You might want to consider using replace_node_sparse() instead.

rdfrest.util.replace_node_sparse(graph, old_node, new_node)[source]

Replace a node by another in graph.

IMPORTANT: this method assumes that old_node will be used in few triples, so it searches for those triples in order to replace them.

You might want to consider using replace_node_dense() instead.

rdfrest.util.urisplit(url)[source]

A better urlsplit.

It differentiates empty querystring/fragment from none. e.g.:

urisplit('http://a.b/c/d') -> ('http', 'a.b', '/c/d', None, None)
urisplit('http://a.b/c/d?') -> ('http', 'a.b', '/c/d', '', None)
urisplit('http://a.b/c/d#') -> ('http', 'a.b', '/c/d', None, '')
urisplit('http://a.b/c/d?#') -> ('http', 'a.b', '/c/d', '', '')
rdfrest.util.uriunsplit(split_uri)[source]

A better urlunsplit.

It differentiates empty querystring/fragment from none. e.g.:

uriunsplit('http', 'a.b', '/c/d', None, None) -> 'http://a.b/c/d'
uriunsplit('http', 'a.b', '/c/d', '', None) -> 'http://a.b/c/d?'
uriunsplit('http', 'a.b', '/c/d', None, '') ->'http://a.b/c/d#'
uriunsplit('http', 'a.b', '/c/d', '', '') -> 'http://a.b/c/d?#'
rdfrest.util.wrap_exceptions(extype)[source]

I return a function decorator wrapping all exceptions as extype.

rdfrest.util.wrap_generator_exceptions(extype)[source]

I return a generator decorator wrapping all exceptions as extype.

class rdfrest.util.Diagnosis(title='diagnosis', errors=None)[source]

I contain a list of problems and eval to True if there is no problem.

append(error_msg)[source]

Append a problem to this diagnosis.

class rdfrest.util.ReadOnlyGraph(store_or_graph='default', identifier=None, namespace_manager=None)[source]

A read-only version of rdflib.Graph.

destroy(configuration)[source]

Raise a ModificationException as this graph is read-only.

commit()[source]

Raise a ModificationException as this graph is read-only.

rollback()[source]

Raise a ModificationException as this graph is read-only.

open(configuration, create=False)[source]

Raise a ModificationException if create, as this graph is read-only.

add((s, p, o))[source]

Raise a ModificationException as this graph is read-only.

addN(quads)[source]

Raise a ModificationException as this graph is read-only.

remove((s, p, o))[source]

Raise a ModificationException as this graph is read-only.

set((subject, predicate, object))[source]

Raise a ModificationException as this graph is read-only.

bind(prefix, namespace, override=True)[source]

Raise a ModificationException as this graph is read-only.

parse(source=None, publicID=None, format=None, location=None, file=None, data=None, **args)[source]

Raise a ModificationException as this graph is read-only.

load(source, publicID=None, format='xml')[source]

Raise a ModificationException as this graph is read-only.

The config module

I provide configuration functions for the rdfrest Service.

rdfrest.util.config.get_service_configuration(configfile_handler=None)[source]

I set rdfrest Service default configuration options and possibly override them with the values extracted from a configuration file.

Parameters:configfile_handler – optional handler of a configuration file
Returns:Configuration object.
rdfrest.util.config.build_service_root_uri(service_config)[source]
Parameters:service_config – SafeConfigParser object containing URI scheme elements
Returns:Ktbs root URI
rdfrest.util.config.apply_logging_config(service_config)[source]

Configures the logging for rdfrest services.

Parameters:service_config – SafeConfigParser object containing a ‘logging’ section
rdfrest.util.config.apply_ns_prefix_config(service_config)[source]

Loads and applies the namespace configuration.

Parameters:service_config – SafeConfigParser object containing a ‘ns_prefix’ section
rdfrest.util.config.apply_plugins_config(service_config)[source]

Loads and applies the plugin configuration.

Parameters:service_config – SafeConfigParser object containing a ‘plugins’ section
rdfrest.util.config.apply_global_config(service_config, **sections)[source]

Loads and applies all global configuration settings (i.e. settings having an impact beyong the configured Service).

Some sections can be individually disabled by using keyword. For example:

apply_global_config(cfg, logging=False, plugins=do_plugins)

will skip the ‘logging’ section, and conditionally apply the ‘plugins’ section (depending on the do_plugins variable).

The proxystore module

I implement an rdflib store that acts as a proxy to a RESTful RDF graph.

class rdfrest.util.proxystore.ProxyStore(configuration=None, identifier=None)[source]
A Proxy store implemention.
Parameters:configuration
Can be a string or a dictionary. May be
passed to __init__() or to open(). Specified as a configuration string (store database connection string). For KTBS, it is preferably a dictionary which may contain credentials for HTTP requests, the URI of the graph and an httpresponse supplied by the client (contains an RDF serialized graph already posted with HTTPLIB2 and the header of the response). If the parameters are in a string, the format should be “key1:value1;key2:value2”. May be passed to __init__() or to open(). Optionnal.
param identifier:
 URIRef identifying the graph to cache in the store.

See http://www.rdflib.net/store/ for the detail of a store. Take store.py for the squeletton.

The real store is on a server accessed with a REST protocol.

prefered_format

The format that the remote server seems to prefer.

Return a tuple (content_type, rdflib_format)

open(configuration, create=False)[source]

Opens the store specified by the configuration string. For the ProxyStore, the identifier is the graph address.

Parameters:
  • configuration – Usually a configuration string of the store (for database connection). May contain credentials for HTTP requests. Can be a string or a dictionary. May be passed to __init__() or to open().
  • create – True to create a store. This not meaningfull for the ProxyStore. Optionnal.
Returns:

  • VALID_STORE on success
  • UNKNOWN No identifier or wrong identifier
  • NO_STORE

force_refresh(clear_cache=False)[source]

Forces the cache to be updated with HTTP specific headers.

If clear_cache is False (default), etags will still be used, so the server may reply with a 304 Not Changed. If clear_cache is True, the cache will be cleared, so the content will have to be resent by the server.

add(triple, context=None, quoted=False)[source]

Add a triple to the store. Apply the modifications on the cache, trigger an exception if data has already been modified on the server.

Parameters:
  • triple – Triple (subject, predicate, object) to add.
  • context
  • quoted – The quoted argument is interpreted by formula-aware stores to indicate this statement is quoted/hypothetical. It should be an error to not specify a context and have the quoted argument be True. It should also be an error for the quoted argument to be True when the store is not formula-aware.
Returns:

remove(triple, context)[source]

Remove the set of triples matching the pattern from the store

Parameters:
  • triple – Triple (subject, predicate, object) to remove.
  • context
Returns:

triples(triple, context=None)[source]

Returns an iterator over all the triples (within the conjunctive graph or just the given context) matching the given pattern.

Parameters:
  • triple – Triple (subject, predicate, object) to remove.
  • context – ProxyStore is not context aware but it’s internal cache IOMemory store is. Avoid context parameter.
Returns:

An iterator over the triples.

commit()[source]

Sends the modifications to the server.

rollback()[source]

Cancel the modifications. Get the graph from the server.

close(commit_pending_transaction=False)[source]

This closes the database connection.

Parameters:commit_pending_transaction – Specifies whether to commit all pending transactions before closing (if the store is transactional).
destroy(configuration)[source]

This destroys the instance of the store identified by the configuration string.

Parameters:configuration – Configuration string identifying the store
query(query, initNs=None, initBindings=None, queryGraph=None, **kw)[source]

I provide SPARQL query processing as a store.

I simply pass through the query to the underlying graph. This prevents an external SPARQL engine to make multiple accesses to that store, which can generate HTTP traffic.

exception rdfrest.util.proxystore.GraphChangedError(url=None, msg=None)[source]

Exception to be raised when the user tries to change graph data but the graph has already changed on the server.

exception rdfrest.util.proxystore.ServerError(url=None, msg=None)[source]

Exception to be raised when the server issues a 5xx error.

exception rdfrest.util.proxystore.StoreIdentifierError(identifier=None)[source]

Exception to be raised when the user tries to create a ProxyStore and to use it immediately with a wrong identifier.

exception rdfrest.util.proxystore.ResourceAccessError(retcode=None, identifier=None, configuration=None)[source]

Exception to be raised when the user tries to create a ProxyStore but the URI (identifier) is not valid or the configuration (e.g credentials) is not valid.

The compat module

I ensure compatibility with older versions of python and other dependencies.

I am automatically loaded when importing rdfrest.