示例#1
0
def delete(uid, soft=True):
    '''
    Delete a resource.

    @param uid (string) Resource UID.
    @param soft (bool) Whether to perform a soft-delete and leave a
    tombstone resource, or wipe any memory of the resource.
    '''
    # If referential integrity is enforced, grab all inbound relationships
    # to break them.
    refint = app_globals.rdfly.config['referential_integrity']
    inbound = True if refint else inbound
    repr_opts = {'incl_inbound': True} if refint else {}

    children = app_globals.rdfly.get_descendants(uid)

    if soft:
        rsrc = LdpFactory.from_stored(uid, repr_opts)
        ret = rsrc.bury_rsrc(inbound)

        for child_uri in children:
            try:
                child_rsrc = LdpFactory.from_stored(
                    app_globals.rdfly.uri_to_uid(child_uri),
                    repr_opts={'incl_children': False})
            except (TombstoneError, ResourceNotExistsError):
                continue
            child_rsrc.bury_rsrc(inbound, tstone_pointer=rsrc.uri)
    else:
        ret = app_globals.rdfly.forget_rsrc(uid, inbound)
        for child_uri in children:
            child_uid = app_globals.rdfly.uri_to_uid(child_uri)
            ret = app_globals.rdfly.forget_rsrc(child_uid, inbound)

    return ret
示例#2
0
def create(parent, slug, **kwargs):
    r"""
    Mint a new UID and create a resource.

    The UID is computed from a given parent UID and a "slug", a proposed path
    relative to the parent. The application will attempt to use the suggested
    path but it may use a different one if a conflict with an existing resource
    arises.

    :param str parent: UID of the parent resource.
    :param str slug: Tentative path relative to the parent UID.
    :param \*\*kwargs: Other parameters are passed to the
      :py:meth:`~lakesuperior.model.ldp_factory.LdpFactory.from_provided`
      method.

    :rtype: str
    :return: UID of the new resource.
    """
    uid = LdpFactory.mint_uid(parent, slug)
    logger.debug('Minted UID for new resource: {}'.format(uid))
    rsrc = LdpFactory.from_provided(uid, **kwargs)

    rsrc.create_or_replace(create_only=True)

    return uid
示例#3
0
    def _containment_rel(self, create):
        """Find the closest parent in the path indicated by the uid and
        establish a containment triple.

        Check the path-wise parent of the new resource. If it exists, add the
        containment relationship with this UID. Otherwise, create a container
        resource as the parent.
        This function may recurse up the path tree until an existing container
        is found.

        E.g. if only fcres:/a exists:
        - If ``fcres:/a/b/c/d`` is being created, a becomes container of
          ``fcres:/a/b/c/d``. Also, containers are created for fcres:a/b and
          ``fcres:/a/b/c``.
        - If ``fcres:/e`` is being created, the root node becomes container of
          ``fcres:/e``.

        :param bool create: Whether the resource is being created. If false,
        the parent container is not updated.
        """
        from lakesuperior.model.ldp_factory import LdpFactory

        if '/' in self.uid.lstrip('/'):
            # Traverse up the hierarchy to find the parent.
            path_components = self.uid.lstrip('/').split('/')
            cnd_parent_uid = '/' + '/'.join(path_components[:-1])
            if rdfly.ask_rsrc_exists(cnd_parent_uid):
                parent_rsrc = LdpFactory.from_stored(cnd_parent_uid)
                if nsc['ldp'].Container not in parent_rsrc.types:
                    raise InvalidResourceError(
                        cnd_parent_uid, 'Parent {} is not a container.')

                parent_uid = cnd_parent_uid
            else:
                parent_rsrc = LdpFactory.new_container(cnd_parent_uid)
                # This will trigger this method again and recurse until an
                # existing container or the root node is reached.
                parent_rsrc.create_or_replace()
                parent_uid = parent_rsrc.uid
        else:
            parent_uid = ROOT_UID

        parent_rsrc = LdpFactory.from_stored(
            parent_uid, repr_opts={'incl_children': False}, handling='none')

        # Only update parent if the resource is new.
        if create:
            add_gr = Graph()
            add_gr.add(
                (nsc['fcres'][parent_uid], nsc['ldp'].contains, self.uri))
            parent_rsrc.modify(RES_UPDATED, add_trp=add_gr)

        # Direct or indirect container relationship.
        return self._add_ldp_dc_ic_rel(parent_rsrc)
示例#4
0
def get_metadata(uid):
    """
    Get metadata (admin triples) of an LDPR resource.

    :param string uid: Resource UID.
    """
    return LdpFactory.from_stored(uid).metadata
示例#5
0
def create_or_replace(uid, stream=None, **kwargs):
    '''
    Create or replace a resource with a specified UID.

    If the resource already exists, all user-provided properties of the
    existing resource are deleted. If the resource exists and the provided
    content is empty, an exception is raised (not sure why, but that's how
    FCREPO4 handles it).

    @param uid (string) UID of the resource to be created or updated.
    @param stream (BytesIO) Content stream. If empty, an empty container is
    created.
    @param **kwargs Other parameters are passed to the
    LdpFactory.from_provided method. Please see the documentation for that
    method for explanation of individual parameters.

    @return string Event type: whether the resource was created or updated.
    '''
    rsrc = LdpFactory.from_provided(uid, stream=stream, **kwargs)

    if not stream and rsrc.is_stored:
        raise InvalidResourceError(
            rsrc.uid,
            'Resource {} already exists and no data set was provided.')

    return rsrc.create_or_replace_rsrc()
示例#6
0
def resurrect(uid):
    """
    Reinstate a buried (soft-deleted) resource.

    :param str uid: Resource UID.
    """
    return LdpFactory.from_stored(uid).resurrect_rsrc()
示例#7
0
def resurrect(uid):
    '''
    Reinstate a buried (soft-deleted) resource.

    @param uid (string) Resource UID.
    '''
    return LdpFactory.from_stored(uid).resurrect_rsrc()
示例#8
0
def is_accept_hdr_rdf_parsable():
    '''
    Check if any of the 'Accept' header values provided is a RDF parsable
    format.
    '''
    for mimetype in request.accept_mimetypes.values():
        if LdpFactory.is_rdf_parsable(mimetype):
            return True
    return False
示例#9
0
def patch_version(uid, ver_uid):
    '''
    Revert to a previous version.

    NOTE: This creates a new version snapshot.

    @param uid (string) Resource UID.
    @param ver_uid (string) Version UID.
    '''
    try:
        LdpFactory.from_stored(uid).revert_to_version(ver_uid)
    except ResourceNotExistsError as e:
        return str(e), 404
    except InvalidResourceError as e:
        return str(e), 409
    except TombstoneError as e:
        return _tombstone_response(e, uid)
    else:
        return '', 204
示例#10
0
def exists(uid):
    """
    Return whether a resource exists (is stored) in the repository.

    :param string uid: Resource UID.
    """
    try:
        exists = LdpFactory.from_stored(uid).is_stored
    except ResourceNotExistsError:
        exists = False
    return exists
示例#11
0
def create_version(uid, ver_uid):
    '''
    Create a resource version.

    @param uid (string) Resource UID.
    @param ver_uid (string) Version UID to be appended to the resource URI.
    NOTE: this is a "slug", i.e. the version URI is not guaranteed to be the
    one indicated.

    @return string Version UID.
    '''
    return LdpFactory.from_stored(uid).create_version(ver_uid)
示例#12
0
def put_resource(uid):
    """
    https://www.w3.org/TR/ldp/#ldpr-HTTP_PUT

    Add or replace a new resource at a specified URI.
    """
    # Parse headers.
    logger.debug('Request headers: {}'.format(request.headers))

    rsp_headers = {'Content-Type': 'text/plain; charset=utf-8'}

    handling, disposition = set_post_put_params()
    stream, mimetype = _bistream_from_req()

    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])
        stream = mimetype = None
    else:
        graph = None

    try:
        evt = rsrc_api.create_or_replace(uid,
                                         stream=stream,
                                         mimetype=mimetype,
                                         graph=graph,
                                         handling=handling,
                                         disposition=disposition)
    except (InvalidResourceError, ResourceExistsError) as e:
        return str(e), 409
    except (ServerManagedTermError, SingleSubjectError) as e:
        return str(e), 412
    except IncompatibleLdpTypeError as e:
        return str(e), 415
    except TombstoneError as e:
        return _tombstone_response(e, uid)

    uri = g.tbox.uid_to_uri(uid)
    if evt == RES_CREATED:
        rsp_code = 201
        rsp_headers['Location'] = rsp_body = uri
        if mimetype and not graph:
            rsp_headers['Link'] = (
                '<{0}/fcr:metadata>; rel="describedby"'.format(uri))
    else:
        rsp_code = 204
        rsp_body = ''
    return rsp_body, rsp_code, rsp_headers
示例#13
0
def create_or_replace(uid, **kwargs):
    r"""
    Create or replace a resource with a specified UID.

    :param string uid: UID of the resource to be created or updated.
    :param \*\*kwargs: Other parameters are passed to the
        :py:meth:`~lakesuperior.model.ldp_factory.LdpFactory.from_provided`
        method.

    :rtype: str
    :return: Event type: whether the resource was created or updated.
    """
    return LdpFactory.from_provided(uid, **kwargs).create_or_replace()
示例#14
0
def create_version(uid, ver_uid):
    """
    Create a resource version.

    :param string uid: Resource UID.
    :param string ver_uid: Version UID to be appended to the resource URI.
      NOTE: this is a "slug", i.e. the version URI is not guaranteed to be the
      one indicated.

    :rtype: str
    :return: Version UID.
    """
    return LdpFactory.from_stored(uid).create_version(ver_uid)
示例#15
0
def post_resource(parent_uid):
    """
    https://www.w3.org/TR/ldp/#ldpr-HTTP_POST

    Add a new resource in a new URI.
    """
    out_headers = std_headers
    try:
        slug = request.headers['Slug']
        logger.debug('Slug: {}'.format(slug))
    except KeyError:
        slug = None

    handling, disposition = set_post_put_params()
    stream, mimetype = _bistream_from_req()

    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
    else:
        is_rdf = False

    try:
        uid = rsrc_api.create(parent_uid,
                              slug,
                              stream=stream,
                              mimetype=mimetype,
                              handling=handling,
                              disposition=disposition)
    except ResourceNotExistsError as e:
        return str(e), 404
    except InvalidResourceError as e:
        return str(e), 409
    except TombstoneError as e:
        return _tombstone_response(e, uid)
    except ServerManagedTermError as e:
        return str(e), 412

    uri = g.tbox.uid_to_uri(uid)
    hdr = {'Location': uri}

    if mimetype and not is_rdf:
        hdr['Link'] = '<{0}/fcr:metadata>; rel="describedby"; anchor="<{0}>"'\
                .format(uri)

    out_headers.update(hdr)

    return uri, 201, out_headers
示例#16
0
def create(parent, slug, **kwargs):
    '''
    Mint a new UID and create a resource.

    The UID is computed from a given parent UID and a "slug", a proposed path
    relative to the parent. The application will attempt to use the suggested
    path but it may use a different one if a conflict with an existing resource
    arises.

    @param parent (string) UID of the parent resource.
    @param slug (string) Tentative path relative to the parent UID.
    @param **kwargs Other parameters are passed to the
    LdpFactory.from_provided method. Please see the documentation for that
    method for explanation of individual parameters.

    @return string UID of the new resource.
    '''
    uid = LdpFactory.mint_uid(parent, slug)
    logger.debug('Minted UID for new resource: {}'.format(uid))
    rsrc = LdpFactory.from_provided(uid, **kwargs)

    rsrc.create_or_replace_rsrc(create_only=True)

    return uid
示例#17
0
def update_delta(uid, remove_trp, add_trp):
    """
    Update a resource graph (LDP-RS or LDP-NR) with sets of add/remove triples.

    A set of triples to add and/or a set of triples to remove may be provided.

    :param string uid: Resource UID.
    :param set(tuple(rdflib.term.Identifier)) remove_trp: Triples to
        remove, as 3-tuples of RDFLib terms.
    :param set(tuple(rdflib.term.Identifier)) add_trp: Triples to
        add, as 3-tuples of RDFLib terms.
    """
    rsrc = LdpFactory.from_stored(uid)
    remove_trp = rsrc.check_mgd_terms(remove_trp)
    add_trp = rsrc.check_mgd_terms(add_trp)

    return rsrc.modify(RES_UPDATED, remove_trp, add_trp)
示例#18
0
def update(uid, update_str, is_metadata=False):
    '''
    Update a resource with a SPARQL-Update string.

    @param uid (string) Resource UID.
    @param update_str (string) SPARQL-Update statements.
    @param is_metadata (bool) Whether the resource metadata is being updated.
    If False, and the resource being updated is a LDP-NR, an error is raised.
    '''
    rsrc = LdpFactory.from_stored(uid)
    if LDP_NR_TYPE in rsrc.ldp_types:
        if is_metadata:
            rsrc.patch_metadata(update_str)
        else:
            raise InvalidResourceError(uid)
    else:
        rsrc.patch(update_str)

    return rsrc
示例#19
0
def update(uid, update_str, is_metadata=False):
    """
    Update a resource with a SPARQL-Update string.

    :param string uid: Resource UID.
    :param string update_str: SPARQL-Update statements.
    :param bool is_metadata: Whether the resource metadata are being updated.

    :raise InvalidResourceError: If ``is_metadata`` is False and the resource
        being updated is a LDP-NR.
    """
    # FCREPO is lenient here and Hyrax requires it.
    rsrc = LdpFactory.from_stored(uid, handling='lenient')
    if LDP_NR_TYPE in rsrc.ldp_types and not is_metadata:
        raise InvalidResourceError(
            'Cannot use this method to update an LDP-NR content.')

    delta = rsrc.sparql_delta(update_str)
    rsrc.modify(RES_UPDATED, *delta)

    return rsrc
示例#20
0
def get(uid, repr_options={}):
    '''
    Get an LDPR resource.

    The resource comes preloaded with user data and metadata as indicated by
    the `repr_options` argument. Any further handling of this resource is done
    outside of a transaction.

    @param uid (string) Resource UID.
    @param repr_options (dict(bool)) Representation options. This is a dict
    that is unpacked downstream in the process. The default empty dict results
    in default values. The accepted dict keys are:
    - incl_inbound: include inbound references. Default: False.
    - incl_children: include children URIs. Default: True.
    - embed_children: Embed full graph of all child resources. Default: False
    '''
    rsrc = LdpFactory.from_stored(uid, repr_options)
    # Load graph before leaving the transaction.
    rsrc.imr

    return rsrc
示例#21
0
    def _add_ldp_dc_ic_rel(self, cont_rsrc):
        """
        Add relationship triples from a parent direct or indirect container.

        :param rdflib.resource.Resouce cont_rsrc:  The container resource.
        """
        cont_p = set(cont_rsrc.metadata.predicates())

        logger.info('Checking direct or indirect containment.')
        logger.debug('Parent predicates: {}'.format(cont_p))

        add_trp = {(self.uri, nsc['fcrepo'].hasParent, cont_rsrc.uri)}

        if self.MBR_RSRC_URI in cont_p and self.MBR_REL_URI in cont_p:
            from lakesuperior.model.ldp_factory import LdpFactory

            s = cont_rsrc.metadata.value(cont_rsrc.uri, self.MBR_RSRC_URI)
            p = cont_rsrc.metadata.value(cont_rsrc_uri, self.MBR_REL_URI)

            if cont_rsrc.metadata[RDF.type:nsc['ldp'].DirectContainer]:
                logger.info('Parent is a direct container.')

                logger.debug('Creating DC triples.')
                o = self.uri

            elif (cont_rsrc.metadata[RDF.type:nsc['ldp'].IndirectContainer]
                  and self.INS_CNT_REL_URI in cont_p):
                logger.info('Parent is an indirect container.')
                cont_rel_uri = cont_rsrc.metadata.value(
                    cont_rsrc.uri, self.INS_CNT_REL_URI)
                o = self.provided_imr.value(self.uri, cont_rel_uri)
                logger.debug('Target URI: {}'.format(o))
                logger.debug('Creating IC triples.')

            target_rsrc = LdpFactory.from_stored(rdfly.uri_to_uid(s))
            target_rsrc.modify(RES_UPDATED, add_trp={(s, p, o)})

        return add_trp
示例#22
0
def get_version(uid, ver_uid):
    '''
    Get version metadata (fcr:versions).
    '''
    return LdpFactory.from_stored(uid).get_version(ver_uid)
示例#23
0
def get_version_info(uid):
    '''
    Get version metadata (fcr:versions).
    '''
    return LdpFactory.from_stored(uid).version_info