Ejemplo n.º 1
0
    def get_next_pid(self, namespace=None, count=None):
        """
        Request next available pid or pids from Fedora, optionally in a specified
        namespace.  Calls :meth:`ApiFacade.getNextPID`.

        .. deprecated :: 0.14
          Mint pids for new objects with
          :func:`eulfedora.models.DigitalObject.get_default_pid`
          instead, or call :meth:`ApiFacade.getNextPID` directly.

        :param namespace: (optional) get the next pid in the specified pid namespace;
            otherwise, Fedora will return the next pid in the configured default namespace.
        :param count: (optional) get the specified number of pids; by default, returns 1 pid
        :rtype: string or list of strings
        """
        # this method should no longer be needed - default pid logic moved to DigitalObject
        warnings.warn(
            """get_next_pid() method is deprecated; you should mint new pids via DigitalObject or ApiFacade.getNextPID() instead.""",
            DeprecationWarning)
        kwargs = {}
        if namespace:
            kwargs['namespace'] = namespace
        elif self.default_pidspace:
            kwargs['namespace'] = self.default_pidspace

        if count:
            kwargs['numPIDs'] = count
        r = self.api.getNextPID(**kwargs)
        nextpids = parse_xml_object(NewPids, r.content, r.url)

        if count is None:
            return nextpids.pids[0]
        else:
            return nextpids.pids
Ejemplo n.º 2
0
    def get_next_pid(self, namespace=None, count=None):
        """
        Request next available pid or pids from Fedora, optionally in a specified
        namespace.  Calls :meth:`ApiFacade.getNextPID`.

        .. deprecated :: 0.14
          Mint pids for new objects with
          :func:`eulfedora.models.DigitalObject.get_default_pid`
          instead, or call :meth:`ApiFacade.getNextPID` directly.

        :param namespace: (optional) get the next pid in the specified pid namespace;
            otherwise, Fedora will return the next pid in the configured default namespace.
        :param count: (optional) get the specified number of pids; by default, returns 1 pid
        :rtype: string or list of strings
        """
        # this method should no longer be needed - default pid logic moved to DigitalObject
        warnings.warn("""get_next_pid() method is deprecated; you should mint new pids via DigitalObject or ApiFacade.getNextPID() instead.""",
                      DeprecationWarning)
        kwargs = {}
        if namespace:
            kwargs['namespace'] = namespace
        elif self.default_pidspace:
            kwargs['namespace'] = self.default_pidspace

        if count:
            kwargs['numPIDs'] = count
        r = self.api.getNextPID(**kwargs)
        nextpids = parse_xml_object(NewPids, r.content, r.url)

        if count is None:
            return nextpids.pids[0]
        else:
            return nextpids.pids
Ejemplo n.º 3
0
def datastream_lastmodified(request, pid, dsid, repo=None,
    as_of_date=None, *args, **kwargs):
    '''Method suitable for use as a a last-modified function with
    :class:`django.views.decorators.http.condition`.  Takes basically
    the same arguments as :meth:`~eulfedora.views.raw_datastream`.
    '''
    try:
        if repo is None:
            repo = Repository()
        resp = repo.api.getDatastream(pid, dsid, asOfDateTime=as_of_date)
        dsprofile = parse_xml_object(DatastreamProfile, resp.content, resp.url)
        if dsprofile:
            return dsprofile.created
    except RequestFailed:
        pass
Ejemplo n.º 4
0
def datastream_lastmodified(request,
                            pid,
                            dsid,
                            repo=None,
                            as_of_date=None,
                            *args,
                            **kwargs):
    '''Method suitable for use as a a last-modified function with
    :class:`django.views.decorators.http.condition`.  Takes basically
    the same arguments as :meth:`~eulfedora.views.raw_datastream`.
    '''
    try:
        if repo is None:
            repo = Repository()
        resp = repo.api.getDatastream(pid, dsid, asOfDateTime=as_of_date)
        dsprofile = parse_xml_object(DatastreamProfile, resp.content, resp.url)
        if dsprofile:
            return dsprofile.created
    except RequestFailed:
        pass
Ejemplo n.º 5
0
def datastream_etag(request, pid, dsid, repo=None, as_of_date=None, **kwargs):
    '''Method suitable for use as an etag function with
    :class:`django.views.decorators.http.condition`.  Takes the same
    arguments as :meth:`~eulfedora.views.raw_datastream`.
    '''
    # if a range is requested and it is not for the entire file,
    # do *NOT* return an etag

    # NOTE: using api directly here instead of object/ds models
    # to avoid making unneeded api calls

    try:
        if repo is None:
            repo = Repository()
        resp = repo.api.getDatastream(pid, dsid, asOfDateTime=as_of_date)
        dsprofile = parse_xml_object(DatastreamProfile, resp.content, resp.url)
        if dsprofile and dsprofile.checksum_type != 'DISABLED':
            return dsprofile.checksum
    except RequestFailed:
        pass

    return None
Ejemplo n.º 6
0
def datastream_etag(request, pid, dsid, repo=None,
    as_of_date=None, **kwargs):
    '''Method suitable for use as an etag function with
    :class:`django.views.decorators.http.condition`.  Takes the same
    arguments as :meth:`~eulfedora.views.raw_datastream`.
    '''
    # if a range is requested and it is not for the entire file,
    # do *NOT* return an etag

    # NOTE: using api directly here instead of object/ds models
    # to avoid making unneeded api calls

    try:
        if repo is None:
            repo = Repository()
        resp = repo.api.getDatastream(pid, dsid, asOfDateTime=as_of_date)
        dsprofile = parse_xml_object(DatastreamProfile, resp.content, resp.url)
        if dsprofile and dsprofile.checksum_type != 'DISABLED':
            return dsprofile.checksum
    except RequestFailed:
        pass

    return None
Ejemplo n.º 7
0
    def find_objects(self, terms=None, type=None, chunksize=None, **kwargs):
        """
        Find objects in Fedora.  Find query should be generated via keyword
        args, based on the fields in Fedora documentation.  By default, the
        query uses a contains (~) search for all search terms.  Calls
        :meth:`ApiFacade.findObjects`. Results seem to return consistently
        in ascending PID order.

        Example usage - search for all objects where the owner contains 'jdoe'::

            repository.find_objects(ownerId='jdoe')

        Supports all search operators provided by Fedora findObjects query (exact,
        gt, gte, lt, lte, and contains).  To specify the type of query for
        a particular search term, call find_objects like this::

            repository.find_objects(ownerId__exact='lskywalker')
            repository.find_objects(date__gt='20010302')

        :param type: type of objects to return; defaults to :class:`DigitalObject`
        :param chunksize: number of objects to return at a time
        :rtype: generator for list of objects
        """
        type = type or self.default_object_type

        find_opts = {'chunksize': chunksize}

        search_operators = {
            'exact': '=',
            'gt': '>',
            'gte': '>=',
            'lt': '<',
            'lte': '<=',
            'contains': '~'
        }

        if terms is not None:
            find_opts['terms'] = terms
        else:
            conditions = []
            for field, value in six.iteritems(kwargs):
                if '__' in field:
                    field, filtr = field.split('__')
                    if filtr not in search_operators:
                        raise Exception("Unsupported search filter '%s'" %
                                        filtr)
                    op = search_operators[filtr]
                else:
                    op = search_operators['contains']  # default search mode

                if field in self.search_fields_aliases:
                    field = self.search_fields_aliases[field]
                if field not in self.search_fields:
                    raise Exception("Error generating Fedora findObjects query: unknown search field '%s'" \
                                    % field)
                if ' ' in value:
                    # if value contains whitespace, it must be delimited with single quotes
                    value = "'%s'" % value
                conditions.append("%s%s%s" % (field, op, value))

            query = ' '.join(conditions)
            find_opts['query'] = query

        r = self.api.findObjects(**find_opts)
        chunk = parse_xml_object(SearchResults, r.content, r.url)
        while True:
            for result in chunk.results:
                yield type(self.api, result.pid)

            if chunk.session_token:
                r = self.api.findObjects(session_token=chunk.session_token,
                                         **find_opts)
                chunk = parse_xml_object(SearchResults, r.content, r.url)
            else:
                break
Ejemplo n.º 8
0
    def find_objects(self, terms=None, type=None, chunksize=None, **kwargs):
        """
        Find objects in Fedora.  Find query should be generated via keyword
        args, based on the fields in Fedora documentation.  By default, the
        query uses a contains (~) search for all search terms.  Calls
        :meth:`ApiFacade.findObjects`. Results seem to return consistently
        in ascending PID order.

        Example usage - search for all objects where the owner contains 'jdoe'::

            repository.find_objects(ownerId='jdoe')

        Supports all search operators provided by Fedora findObjects query (exact,
        gt, gte, lt, lte, and contains).  To specify the type of query for
        a particular search term, call find_objects like this::

            repository.find_objects(ownerId__exact='lskywalker')
            repository.find_objects(date__gt='20010302')

        :param type: type of objects to return; defaults to :class:`DigitalObject`
        :param chunksize: number of objects to return at a time
        :rtype: generator for list of objects
        """
        type = type or self.default_object_type

        find_opts = {'chunksize' : chunksize}

        search_operators = {
            'exact': '=',
            'gt': '>',
            'gte': '>=',
            'lt': '<',

            'lte': '<=',
            'contains': '~'
        }

        if terms is not None:
            find_opts['terms'] = terms
        else:
            conditions = []
            for field, value in six.iteritems(kwargs):
                if '__' in field:
                    field, filter = field.split('__')
                    if filter not in search_operators:
                        raise Exception("Unsupported search filter '%s'" % filter)
                    op = search_operators[filter]
                else:
                    op = search_operators['contains']   # default search mode

                if field in self.search_fields_aliases:
                    field = self.search_fields_aliases[field]
                if field not in self.search_fields:
                    raise Exception("Error generating Fedora findObjects query: unknown search field '%s'" \
                                    % field)
                if ' ' in value:
                    # if value contains whitespace, it must be delimited with single quotes
                    value = "'%s'" % value
                conditions.append("%s%s%s" % (field, op, value))

            query = ' '.join(conditions)
            find_opts['query'] = query

        r = self.api.findObjects(**find_opts)
        chunk = parse_xml_object(SearchResults, r.content, r.url)
        while True:
            for result in chunk.results:
                yield type(self.api, result.pid)

            if chunk.session_token:
                r = self.api.findObjects(session_token=chunk.session_token, **find_opts)
                chunk = parse_xml_object(SearchResults, r.content, r.url)
            else:
                break
Ejemplo n.º 9
0
    def fs_members(self, *els, **kwargs):
        """Get all the members of a "container" element (i.e. an object treated
        as a directory by fuse).
        
        :param els: list of path elements
        :params writable_only: if True, only return members that are capable of
            being written
        :rtype: list
        """

        if "writable_only" in kwargs:
            writable_only = kwargs["writable_only"]
        else:
            writable_only = False

        members = []
        if len(els) == 0:  # top level
            # no elements - top-level view of the object itself
            # find all members of this object that should be listed in the directory
            # - should be strings, not unicode
            if not writable_only:
                members.append(".info")
            if len(self.history):
                members.append(".versions")

            # add all datastreams - using datastream id for directory listing
            members.extend([str(dsid) for dsid in self.ds_list.keys()])
            # relations to other objects - use short-hand rel names for directory names
            members.extend(self.rel_shortnames)

            if not writable_only:
                # add methods - using method name for directory listing
                # NOTE: it's possible to have duplicate method names defined
                # on different service objects... current implementation does
                # *not* take this into account
                self.method_names = {}
                for sdef, method_list in self.methods.iteritems():
                    # FIXME: any way to exclude methods that require parameters?
                    for m in method_list:
                        self.method_names[m] = sdef

                members.extend(self.method_names)

        elif els[0] == ".versions":
            # list revisions of this object
            # (not completely implemented...)
            if len(els) == 1:
                members = [str(dt) for dt in self.history]
            else:
                # TODO: get a *versioned* list of datastreams
                # (don't list ones that didn't exist at the specified time!)
                data, url = self.api.listDatastreams(self.pid)
                dsobj = parse_xml_object(ObjectDatastreams, data, url)
                return [str(ds.dsid) for ds in dsobj.datastreams]

        # related objects
        elif els[0] in self.rel_shortnames:
            # top level: directory with objects related by the specified short-name relation
            if len(els) == 1:
                rel_uri = self.rel_shortnames[els[0]]
                members = self.related_objects[rel_uri]

        return members