Source code for rdfrest.cores.hosted

#    This file is part of RDF-REST <http://champin.net/2012/rdfrest>
#    Copyright (C) 2011-2012 Pierre-Antoine Champin <pchampin@liris.cnrs.fr> /
#    Universite de Lyon <http://www.universite-lyon.fr>
#
#    RDF-REST is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Lesser General Public License as published
#    by the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    RDF-REST is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Lesser General Public License for more details.
#
#    You should have received a copy of the GNU Lesser General Public License
#    along with RDF-REST.  If not, see <http://www.gnu.org/licenses/>.

"""
I implement :class:`.interface.ICore` as a resource "hosted" by another one.
"""
from functools import wraps
from rdflib import RDF, URIRef

from ..exceptions import MethodNotAllowedError
from ..cores import ICore
from ..wrappers import get_wrapped
from ..util import coerce_to_uri, urisplit

[docs]class HostedCore(ICore): """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. :param host_resource: the host resource :type host_resource: :class:`.interface.ICore` :param uri: this resource's URI (may be relative to host's) :type uri: basestring :param forward_params: whether parameters should be forwarded to host (see below) :type forward_params: bool 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). .. attribute:: uri I implement :attr:`.interface.ICore.uri`. I hold this resource's URI as defined at `__init__` time. """ def __init__(self, host_resource, uri, forward_params=True): # not calling parents __init__ #pylint: disable=W0231 assert isinstance(host_resource, ICore) self.host = host_resource self.uri = coerce_to_uri(uri, host_resource.uri) self.forward_params = forward_params def __str__(self): return "<%s>" % self.uri
[docs] def factory(self, uri, rdf_types=None, _no_spawn=False): """I implement :meth:`.interface.ICore.factory`. I simply rely on my host's factory. """ return self.host.factory(uri, rdf_types, _no_spawn)
[docs] def get_state(self, parameters=None): """I implement :meth:`.interface.ICore.get_state`. I simply return my host's state. """ if not self.forward_params: parameters = None return self.host.get_state(parameters)
[docs] def force_state_refresh(self, parameters=None): """I implement `interface.ICore.force_state_refresh`. I simply force a state refresh on my host. """ if not self.forward_params: parameters = None self.host.force_state_refresh(parameters)
[docs] def edit(self, parameters=None, clear=False, _trust=False): """I implement :meth:`.interface.ICore.edit`. I simply return my host's edit context. """ if not self.forward_params: parameters = None return self.host.edit(parameters, clear, _trust)
[docs] def post_graph(self, graph, parameters=None, _trust=False, _created=None, _rdf_type=None): """I implement :meth:`.interface.ICore.post_graph`. No data can be posted to a hosted resource; it should be posted to the host resource instead. """ # unused arguments #pylint: disable=W0613 raise MethodNotAllowedError("Can not post to hosted resource <%s>" % self.uri)
[docs] def delete(self, parameters=None, _trust=False): """I implement :meth:`.interface.ICore.delete`. A hosted resource can not be deleted. The host resource should be altered instead. """ # unused arguments #pylint: disable=W0613 raise MethodNotAllowedError("Can not delete hosted resource <%s>" % self.uri) ################################################################ # # Other public method spefific to this implementation #
def __eq__(self, other): """Two instances with the same URI are considered equal """ return (isinstance(other, HostedCore) and other.uri == self.uri) def __hash__(self): """Two instances with the same URI will have the same hash """ return hash(HostedCore) ^ hash(self.uri) @classmethod
[docs] def handle_fragments(cls, factory): """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. """ @wraps(factory) def decorated_factory(self_or_cls, uri, rdf_types=None, _no_spawn=False): """I wrap a resource factory to handle URIs with frag-id.""" assert rdf_types is None or isinstance(rdf_types, list) fragid = urisplit(uri)[4] if fragid is None: return factory(self_or_cls, uri, rdf_types, _no_spawn) else: uri = URIRef(uri) host = factory(self_or_cls, URIRef(uri[:-len(fragid)-1]), None, _no_spawn) if host is not None: if rdf_types: py_class = get_wrapped(cls, rdf_types) else: py_class = cls return py_class(host, uri) else: return None return decorated_factory