From a64b57551b4c780e7c2eeb7666ef4b7458ef6ac0 Mon Sep 17 00:00:00 2001 From: Stefano Cossu Date: Sun, 15 Apr 2018 15:02:29 -0500 Subject: [PATCH] Allow creating resources providing RDF bytestring. Also resolves #56. --- docs/usage.rst | 12 ++++++++++++ lakesuperior/endpoints/ldp.py | 28 +++++++++++++++------------- lakesuperior/model/ldp_factory.py | 9 ++++++++- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/docs/usage.rst b/docs/usage.rst index 635b0b0..acfc763 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -152,10 +152,22 @@ Create an LDP-NR (non-RDF source):: ... uid, stream=BytesIO(data), mimetype='text/plain') '_create_' +Create or replace providing a serialized RDF byte stream:: + + >>> uid = '/rsrc_from_rdf' + >>> rdf = b'<#a1> a .' + >>> rsrc_api.create_or_replace(uid, rdf_data=rdf, rdf_fmt='turtle') + +Relative URIs such as ``<#a1>`` will be resolved relative to the resource URI. + Create under a known parent, providing a slug (POST style):: >>> rsrc_api.create('/rsrc_from_stream', 'res1') +This will create ``/rsrc_from_stream/res1`` if not existing; otherwise the +resource URI will have a random UUID4 instead of ``res1``. + +To use a random UUID by default, use ``None`` for the second argument. Retrieve Resources ~~~~~~~~~~~~~~~~~~ diff --git a/lakesuperior/endpoints/ldp.py b/lakesuperior/endpoints/ldp.py index 1cebf03..f22645c 100644 --- a/lakesuperior/endpoints/ldp.py +++ b/lakesuperior/endpoints/ldp.py @@ -228,16 +228,17 @@ def post_resource(parent_uid): if LdpFactory.is_rdf_parsable(mimetype): # If the content is RDF, localize in-repo URIs. global_rdf = stream.read() - local_rdf = g.tbox.localize_payload(global_rdf) - stream = BytesIO(local_rdf) - is_rdf = True + rdf_data = g.tbox.localize_payload(global_rdf) + rdf_fmt = mimetype + stream = mimetype = None else: - is_rdf = False + rdf_data = rdf_fmt = None try: uid = rsrc_api.create( - parent_uid, slug, stream=stream, mimetype=mimetype, - handling=handling, disposition=disposition) + parent_uid, slug, stream=stream, mimetype=mimetype, + rdf_data=rdf_data, rdf_fmt=rdf_fmt, handling=handling, + disposition=disposition) except ResourceNotExistsError as e: return str(e), 404 except InvalidResourceError as e: @@ -279,16 +280,17 @@ def put_resource(uid): if LdpFactory.is_rdf_parsable(mimetype): # If the content is RDF, localize in-repo URIs. global_rdf = stream.read() - local_rdf = g.tbox.localize_payload(global_rdf) - graph = Graph().parse( - data=local_rdf, format=mimetype, publicID=nsc['fcres'][uid]) + rdf_data = g.tbox.localize_payload(global_rdf) + rdf_fmt = mimetype stream = mimetype = None else: - graph = None + rdf_data = rdf_fmt = None try: - evt = rsrc_api.create_or_replace(uid, stream=stream, mimetype=mimetype, - graph=graph, handling=handling, disposition=disposition) + evt = rsrc_api.create_or_replace( + uid, stream=stream, mimetype=mimetype, + rdf_data=rdf_data, rdf_fmt=rdf_fmt, handling=handling, + disposition=disposition) except (InvalidResourceError, ResourceExistsError) as e: return str(e), 409 except (ServerManagedTermError, SingleSubjectError) as e: @@ -302,7 +304,7 @@ def put_resource(uid): if evt == RES_CREATED: rsp_code = 201 rsp_headers['Location'] = rsp_body = uri - if mimetype and not graph: + if mimetype and not rdf_data: rsp_headers['Link'] = ( '<{0}/fcr:metadata>; rel="describedby"'.format(uri)) else: diff --git a/lakesuperior/model/ldp_factory.py b/lakesuperior/model/ldp_factory.py index bd0d896..70c0f4d 100644 --- a/lakesuperior/model/ldp_factory.py +++ b/lakesuperior/model/ldp_factory.py @@ -78,7 +78,9 @@ def from_stored(uid, repr_opts={}, **kwargs): @staticmethod - def from_provided(uid, mimetype=None, stream=None, graph=None, **kwargs): + def from_provided( + uid, mimetype=None, stream=None, graph=None, rdf_data=None, + rdf_fmt=None, **kwargs): r""" Create and LDPR instance from provided data. @@ -92,12 +94,17 @@ def from_provided(uid, mimetype=None, stream=None, graph=None, **kwargs): :param IOStream stream: The provided data stream. :param rdflib.Graph graph: Initial graph to populate the resource with. This can be used for LDP-RS and LDP-NR types alike. + :param bytes rdf_data: Serialized RDF to build the initial graph. + :param str rdf_fmt: Serialization format of RDF data. :param \*\*kwargs: Arguments passed to the LDP class constructor. :raise ValueError: if ``mimetype`` is specified but no data stream is provided. """ uri = nsc['fcres'][uid] + if rdf_data: + graph = Graph().parse( + data=rdf_data, format=rdf_fmt, publicID=nsc['fcres'][uid]) provided_imr = Graph(identifier=uri) if graph: