Source code for oldman.rest.controller

from rdflib import Graph
from rdflib.plugin import PluginException, plugins
from logging import getLogger
from rdflib.serializer import Serializer
from .crud import HashLessCRUDer, JSON_TYPES
from oldman.vocabulary import HTTP_POST
from oldman.exception import OMResourceNotFoundException, OMForbiddenOperationException, OMRequiredAuthenticationException
from oldman.exception import OMMethodNotAllowedException, OMBadRequestException, OMObjectNotFoundError
from oldman.exception import OMNotAcceptableException
from negotiator import ContentNegotiator, ContentType, AcceptParameters


[docs]class HTTPController(object): """ HTTP. TODO: check declared methods (only GET and HEAD are implicit). """ DEFAULT_CONFIG = {'allow_put_new_type_existing_resource': False, 'allow_put_remove_type_existing_resource': False, 'allow_put_new_resource': True } def __init__(self, manager, config={}): self._logger = getLogger(__name__) self._manager = manager # For operations except POST self._cruder = HashLessCRUDer(manager) self._config = self.DEFAULT_CONFIG.copy() self._config.update(config) self._negotiator = None self._init_content_negotiator() def _init_content_negotiator(self): #TODO: use config instead default_content_type = "application/ld+json" default_accept_params = AcceptParameters(ContentType(default_content_type)) # rdf types rdf_types = set([plugin.name for plugin in plugins(kind=Serializer) if "/" in plugin.name]) #Blacklisted because mapped to TriX that requires a context-aware store blacklisted_types = ["application/xml"] #TODO: consider other types accepted_types = list(rdf_types.difference(blacklisted_types)) + ["application/json"] self._logger.debug("Accepted types: %s" % accepted_types) acceptable_params = [default_accept_params] + [AcceptParameters(ContentType(ct)) for ct in accepted_types] self._negotiator = ContentNegotiator(default_accept_params, acceptable_params)
[docs] def get(self, hashless_iri, accept_header="*/*", **kwargs): """ TODO: describe. No support declaration required. """ self._logger.debug("Accept header: %s" % accept_header) accepted_type = self._negotiator.negotiate(accept=accept_header) if accepted_type is None: raise OMNotAcceptableException() content_type = str(accepted_type.content_type) self._logger.debug("Selected content-type: %s" % content_type) try: return self._cruder.get(hashless_iri, content_type) except OMObjectNotFoundError: raise OMResourceNotFoundException()
[docs] def head(self, hashless_iri, **kwargs): """ TODO: describe. No support declaration required. """ #TODO: consider a more efficient implementation try: self._cruder.get(hashless_iri, None) except OMObjectNotFoundError: raise OMResourceNotFoundException()
[docs] def post(self, hashless_iri, content_type=None, payload=None, **kwargs): """ TODO: categorize the resource to decide what to do. Support declaration and implementation are required. """ if content_type is None: raise OMBadRequestException("Content type is required.") #if payload is None: # raise BadRequestException("No payload given.") # Must be its ID (we do not consider resources with hash IRIs) resource = self._manager.get(id=hashless_iri) if resource is None: raise OMResourceNotFoundException() operation = resource.get_operation(HTTP_POST) if operation is not None: graph = Graph() try: if content_type in JSON_TYPES: resource = self._manager.get(hashless_iri=hashless_iri) graph.parse(data=payload, format="json-ld", publicID=hashless_iri, context=resource.context) else: graph.parse(data=payload, format=content_type, publicID=hashless_iri) except PluginException: raise OMNotAcceptableException() #TODO: add arguments return operation(resource, graph=graph, content_type=content_type) #TODO: When error code is 405, alternatives must be given. raise OMMethodNotAllowedException()
[docs] def put(self, hashless_iri, content_type=None, payload=None, **kwargs): """ TODO: describe. No support declaration required. """ if content_type is None: raise OMBadRequestException("Content type is required.") if payload is None: raise OMBadRequestException("No payload given.") return self._cruder.update(self, hashless_iri, payload, content_type, allow_new_type=False, allow_type_removal=False, allow_put_new_resource=True)
[docs] def delete(self, hashless_iri, **kwargs): """ TODO: describe. No declaration required. """ self._cruder.delete(hashless_iri)
[docs] def options(self, hashless_iri, **kwargs): """ TODO: implement it """ raise NotImplementedError("")
[docs] def patch(self, hashless_iri, content_type=None, payload=None, **kwargs): """ TODO: implement it """ if content_type is None: raise OMBadRequestException("Content type is required.") if payload is None: raise OMBadRequestException("No payload given.") raise NotImplementedError("PATCH is not yet supported.")